bpo-43962: Fix _PyInterpreterState_IDIncref() (GH-25683) (GH-25686)
https://github.com/python/cpython/commit/77db337f1e69213e62ba79a797540cc4ac2... commit: 77db337f1e69213e62ba79a797540cc4ac23492e branch: 3.8 author: Victor Stinner <vstinner@python.org> committer: vstinner <vstinner@python.org> date: 2021-04-28T15:46:57+02:00 summary: bpo-43962: Fix _PyInterpreterState_IDIncref() (GH-25683) (GH-25686) _PyInterpreterState_IDIncref() now calls _PyInterpreterState_IDInitref() and always increments id_refcount. (cherry picked from commit 32c5a174445ec93747240cd8472012276ed27acf) files: A Misc/NEWS.d/next/C API/2021-04-28-13-13-07.bpo-43962.9Jzs5X.rst M Include/internal/pycore_pystate.h M Objects/interpreteridobject.c M Python/pystate.c diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index 96d5e31d83a6e9..18105335363a45 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -140,7 +140,7 @@ struct _is { PyAPI_FUNC(struct _is*) _PyInterpreterState_LookUpID(PY_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 *); 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 94f5dd709bbda0..19e86a2e0b0f77 100644 --- a/Objects/interpreteridobject.c +++ b/Objects/interpreteridobject.c @@ -23,15 +23,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 b1d0f1cbec428a..56c184e43ae0ef 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -473,24 +473,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);
participants (1)
-
vstinner