Skip to content

Commit 6de3080

Browse files
vstinnermiss-islington
authored andcommitted
bpo-43962: Fix _PyInterpreterState_IDIncref() (pythonGH-25683)
_PyInterpreterState_IDIncref() now calls _PyInterpreterState_IDInitref() and always increments id_refcount. (cherry picked from commit 32c5a17) Co-authored-by: Victor Stinner <vstinner@python.org>
1 parent cf9d65c commit 6de3080

4 files changed

Lines changed: 22 additions & 10 deletions

File tree

‎Include/internal/pycore_interp.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ struct _xidregitem {
182182
PyAPI_FUNC(struct _is*) _PyInterpreterState_LookUpID(int64_t);
183183

184184
PyAPI_FUNC(int) _PyInterpreterState_IDInitref(struct _is *);
185-
PyAPI_FUNC(void) _PyInterpreterState_IDIncref(struct _is *);
185+
PyAPI_FUNC(int) _PyInterpreterState_IDIncref(struct _is *);
186186
PyAPI_FUNC(void) _PyInterpreterState_IDDecref(struct _is *);
187187

188188
#ifdef __cplusplus
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
_PyInterpreterState_IDIncref() now calls _PyInterpreterState_IDInitref() and
2+
always increments id_refcount. Previously, calling
3+
_xxsubinterpreters.get_current() could create an id_refcount inconsistency
4+
when a _xxsubinterpreters.InterpreterID object was deallocated. Patch by
5+
Victor Stinner.

‎Objects/interpreteridobject.c‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,21 @@ newinterpid(PyTypeObject *cls, int64_t id, int force)
2424
}
2525
}
2626

27+
if (interp != NULL) {
28+
if (_PyInterpreterState_IDIncref(interp) < 0) {
29+
return NULL;
30+
}
31+
}
32+
2733
interpid *self = PyObject_New(interpid, cls);
2834
if (self == NULL) {
35+
if (interp != NULL) {
36+
_PyInterpreterState_IDDecref(interp);
37+
}
2938
return NULL;
3039
}
3140
self->id = id;
3241

33-
if (interp != NULL) {
34-
_PyInterpreterState_IDIncref(interp);
35-
}
3642
return self;
3743
}
3844

‎Python/pystate.c‎

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -493,24 +493,25 @@ _PyInterpreterState_IDInitref(PyInterpreterState *interp)
493493
}
494494

495495

496-
void
496+
int
497497
_PyInterpreterState_IDIncref(PyInterpreterState *interp)
498498
{
499-
if (interp->id_mutex == NULL) {
500-
return;
499+
if (_PyInterpreterState_IDInitref(interp) < 0) {
500+
return -1;
501501
}
502+
502503
PyThread_acquire_lock(interp->id_mutex, WAIT_LOCK);
503504
interp->id_refcount += 1;
504505
PyThread_release_lock(interp->id_mutex);
506+
return 0;
505507
}
506508

507509

508510
void
509511
_PyInterpreterState_IDDecref(PyInterpreterState *interp)
510512
{
511-
if (interp->id_mutex == NULL) {
512-
return;
513-
}
513+
assert(interp->id_mutex != NULL);
514+
514515
struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate;
515516
PyThread_acquire_lock(interp->id_mutex, WAIT_LOCK);
516517
assert(interp->id_refcount != 0);

0 commit comments

Comments
 (0)