Skip to content

Commit 32c5a17

Browse files
authored
bpo-43962: Fix _PyInterpreterState_IDIncref() (GH-25683)
_PyInterpreterState_IDIncref() now calls _PyInterpreterState_IDInitref() and always increments id_refcount.
1 parent 21b02b5 commit 32c5a17

File tree

4 files changed

+22
-10
lines changed

4 files changed

+22
-10
lines changed

Include/internal/pycore_interp.h

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

340340
PyAPI_FUNC(int) _PyInterpreterState_IDInitref(struct _is *);
341-
PyAPI_FUNC(void) _PyInterpreterState_IDIncref(struct _is *);
341+
PyAPI_FUNC(int) _PyInterpreterState_IDIncref(struct _is *);
342342
PyAPI_FUNC(void) _PyInterpreterState_IDDecref(struct _is *);
343343

344344
#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
@@ -538,24 +538,25 @@ _PyInterpreterState_IDInitref(PyInterpreterState *interp)
538538
}
539539

540540

541-
void
541+
int
542542
_PyInterpreterState_IDIncref(PyInterpreterState *interp)
543543
{
544-
if (interp->id_mutex == NULL) {
545-
return;
544+
if (_PyInterpreterState_IDInitref(interp) < 0) {
545+
return -1;
546546
}
547+
547548
PyThread_acquire_lock(interp->id_mutex, WAIT_LOCK);
548549
interp->id_refcount += 1;
549550
PyThread_release_lock(interp->id_mutex);
551+
return 0;
550552
}
551553

552554

553555
void
554556
_PyInterpreterState_IDDecref(PyInterpreterState *interp)
555557
{
556-
if (interp->id_mutex == NULL) {
557-
return;
558-
}
558+
assert(interp->id_mutex != NULL);
559+
559560
struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate;
560561
PyThread_acquire_lock(interp->id_mutex, WAIT_LOCK);
561562
assert(interp->id_refcount != 0);

0 commit comments

Comments
 (0)