@@ -3348,11 +3348,13 @@ try_acquire_interp_guard(PyInterpreterState *interp)
33483348{
33493349 assert (interp != NULL );
33503350 _PyRWMutex_RLock (& interp -> finalization_guards .lock );
3351+
33513352 if (_PyInterpreterState_GetFinalizing (interp ) != NULL ) {
33523353 _PyRWMutex_RUnlock (& interp -> finalization_guards .lock );
33533354 assert (_Py_atomic_load_ssize_relaxed (& interp -> finalization_guards .countdown ) == 0 );
33543355 return NULL ;
33553356 }
3357+
33563358 _Py_atomic_add_ssize (& interp -> finalization_guards .countdown , 1 );
33573359 _PyRWMutex_RUnlock (& interp -> finalization_guards .lock );
33583360 return (PyInterpreterGuard * )interp ;
@@ -3363,12 +3365,14 @@ PyInterpreterGuard_FromCurrent(void)
33633365{
33643366 PyInterpreterState * interp = _PyInterpreterState_GET ();
33653367 assert (interp != NULL );
3368+
33663369 PyInterpreterGuard * guard = try_acquire_interp_guard (interp );
33673370 if (guard == NULL ) {
33683371 PyErr_SetString (PyExc_PythonFinalizationError ,
33693372 "cannot acquire finalization guard anymore" );
33703373 return NULL ;
33713374 }
3375+
33723376 return guard ;
33733377}
33743378
@@ -3377,9 +3381,11 @@ PyInterpreterGuard_Close(PyInterpreterGuard *guard)
33773381{
33783382 PyInterpreterState * interp = guard -> interp ;
33793383 assert (interp != NULL );
3384+
33803385 _PyRWMutex_RLock (& interp -> finalization_guards .lock );
33813386 Py_ssize_t old = _Py_atomic_add_ssize (& interp -> finalization_guards .countdown , -1 );
33823387 _PyRWMutex_RUnlock (& interp -> finalization_guards .lock );
3388+
33833389 assert (old > 0 );
33843390 if (old <= 0 ) {
33853391 Py_FatalError ("interpreter has negative guard count, likely due"
@@ -3392,13 +3398,15 @@ PyInterpreterView_FromCurrent(void)
33923398{
33933399 PyInterpreterState * interp = _PyInterpreterState_GET ();
33943400 assert (interp != NULL );
3395- /* PyInterpreterView_Close() can be called without an attached thread
3396- state, so we have to use the raw allocator. */
3401+
3402+ // PyInterpreterView_Close() can be called without an attached thread
3403+ // state, so we have to use the raw allocator.
33973404 PyInterpreterView * view = PyMem_RawMalloc (sizeof (PyInterpreterView ));
33983405 if (view == NULL ) {
33993406 PyErr_NoMemory ();
34003407 return NULL ;
34013408 }
3409+
34023410 view -> refcount = 1 ;
34033411 view -> id = interp -> id ;
34043412 return view ;
@@ -3420,7 +3428,8 @@ PyInterpreterGuard_FromView(PyInterpreterView *view)
34203428 assert (view != NULL );
34213429 int64_t interp_id = view -> id ;
34223430 assert (interp_id >= 0 );
3423- /* Interpreters cannot be deleted while we hold the runtime lock. */
3431+
3432+ // Interpreters cannot be deleted while we hold the runtime lock.
34243433 _PyRuntimeState * runtime = & _PyRuntime ;
34253434 HEAD_LOCK (runtime );
34263435 PyInterpreterState * interp = interp_look_up_id (runtime , interp_id );
@@ -3497,6 +3506,31 @@ PyThreadState_Ensure(PyInterpreterGuard *guard)
34973506 return (PyThreadState * )& NO_TSTATE_SENTINEL ;
34983507}
34993508
3509+ PyThreadState *
3510+ PyThreadState_EnsureFromView (PyInterpreterView * view )
3511+ {
3512+ assert (view != NULL );
3513+ PyInterpreterGuard * guard = PyInterpreterGuard_FromView (view );
3514+ if (guard == NULL ) {
3515+ return NULL ;
3516+ }
3517+
3518+ PyThreadState * tstate = PyThreadState_Ensure (guard );
3519+ if (tstate == NULL ) {
3520+ PyInterpreterGuard_Close (guard );
3521+ return NULL ;
3522+ }
3523+
3524+ if (tstate -> ensure .owned_guard != NULL ) {
3525+ assert (tstate -> ensure .owned_guard -> interp == guard -> interp );
3526+ PyInterpreterGuard_Close (guard );
3527+ } else {
3528+ tstate -> ensure .owned_guard = guard ;
3529+ }
3530+
3531+ return tstate ;
3532+ }
3533+
35003534void
35013535PyThreadState_Release (PyThreadState * old_tstate )
35023536{
@@ -3506,23 +3540,30 @@ PyThreadState_Release(PyThreadState *old_tstate)
35063540 if (remaining < 0 ) {
35073541 Py_FatalError ("PyThreadState_Release() called more times than PyThreadState_Ensure()" );
35083542 }
3509- // The thread view might be NULL
3543+
3544+ if (remaining != 0 ) {
3545+ return ;
3546+ }
3547+
35103548 PyThreadState * to_restore ;
35113549 if (old_tstate == (PyThreadState * )& NO_TSTATE_SENTINEL ) {
35123550 to_restore = NULL ;
35133551 }
35143552 else {
35153553 to_restore = old_tstate ;
35163554 }
3517- if ( remaining == 0 ) {
3518- if ( tstate -> ensure .delete_on_release ) {
3519- PyThreadState_Clear (tstate );
3520- PyThreadState_Swap ( to_restore );
3521- PyThreadState_Delete ( tstate );
3522- } else {
3523- PyThreadState_Swap ( to_restore );
3524- }
3555+
3556+ assert ( tstate -> ensure . delete_on_release == 1 || tstate -> ensure .delete_on_release == 0 );
3557+ if (tstate -> ensure . delete_on_release ) {
3558+ PyThreadState_Clear ( tstate );
3559+ PyThreadState_Swap ( to_restore );
3560+ PyThreadState_Delete ( tstate );
3561+ } else {
3562+ PyThreadState_Swap ( to_restore );
35253563 }
35263564
3527- return ;
3565+ if (tstate -> ensure .owned_guard != NULL ) {
3566+ PyInterpreterGuard_Close (tstate -> ensure .owned_guard );
3567+ tstate -> ensure .owned_guard = NULL ;
3568+ }
35283569}
0 commit comments