From 6de308009b8e4ec67a1cb1764855eb4178471171 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 28 Apr 2021 13:40:44 +0200 Subject: [PATCH] bpo-43962: Fix _PyInterpreterState_IDIncref() (GH-25683) _PyInterpreterState_IDIncref() now calls _PyInterpreterState_IDInitref() and always increments id_refcount. (cherry picked from commit 32c5a174445ec93747240cd8472012276ed27acf) Co-authored-by: Victor Stinner --- Include/internal/pycore_interp.h | 2 +- .../C API/2021-04-28-13-13-07.bpo-43962.9Jzs5X.rst | 5 +++++ Objects/interpreteridobject.c | 12 +++++++++--- Python/pystate.c | 13 +++++++------ 4 files changed, 22 insertions(+), 10 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2021-04-28-13-13-07.bpo-43962.9Jzs5X.rst diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index 551ad833bb6927..c6419522329bf3 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -182,7 +182,7 @@ struct _xidregitem { PyAPI_FUNC(struct _is*) _PyInterpreterState_LookUpID(int64_t); PyAPI_FUNC(int) _PyInterpreterState_IDInitref(struct _is *); -PyAPI_FUNC(void) _PyInterpreterState_IDIncref(struct _is *); +PyAPI_FUNC(int) _PyInterpreterState_IDIncref(struct _is *); PyAPI_FUNC(void) _PyInterpreterState_IDDecref(struct _is *); #ifdef __cplusplus diff --git a/Misc/NEWS.d/next/C API/2021-04-28-13-13-07.bpo-43962.9Jzs5X.rst b/Misc/NEWS.d/next/C API/2021-04-28-13-13-07.bpo-43962.9Jzs5X.rst new file mode 100644 index 00000000000000..32164162f90ad0 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2021-04-28-13-13-07.bpo-43962.9Jzs5X.rst @@ -0,0 +1,5 @@ +_PyInterpreterState_IDIncref() now calls _PyInterpreterState_IDInitref() and +always increments id_refcount. Previously, calling +_xxsubinterpreters.get_current() could create an id_refcount inconsistency +when a _xxsubinterpreters.InterpreterID object was deallocated. Patch by +Victor Stinner. diff --git a/Objects/interpreteridobject.c b/Objects/interpreteridobject.c index 39bde97269590b..46239100dcb7b7 100644 --- a/Objects/interpreteridobject.c +++ b/Objects/interpreteridobject.c @@ -24,15 +24,21 @@ newinterpid(PyTypeObject *cls, int64_t id, int force) } } + if (interp != NULL) { + if (_PyInterpreterState_IDIncref(interp) < 0) { + return NULL; + } + } + interpid *self = PyObject_New(interpid, cls); if (self == NULL) { + if (interp != NULL) { + _PyInterpreterState_IDDecref(interp); + } return NULL; } self->id = id; - if (interp != NULL) { - _PyInterpreterState_IDIncref(interp); - } return self; } diff --git a/Python/pystate.c b/Python/pystate.c index 9beefa8e20c444..9e6208b527f154 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -493,24 +493,25 @@ _PyInterpreterState_IDInitref(PyInterpreterState *interp) } -void +int _PyInterpreterState_IDIncref(PyInterpreterState *interp) { - if (interp->id_mutex == NULL) { - return; + if (_PyInterpreterState_IDInitref(interp) < 0) { + return -1; } + PyThread_acquire_lock(interp->id_mutex, WAIT_LOCK); interp->id_refcount += 1; PyThread_release_lock(interp->id_mutex); + return 0; } void _PyInterpreterState_IDDecref(PyInterpreterState *interp) { - if (interp->id_mutex == NULL) { - return; - } + assert(interp->id_mutex != NULL); + struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate; PyThread_acquire_lock(interp->id_mutex, WAIT_LOCK); assert(interp->id_refcount != 0);