@@ -1373,12 +1373,8 @@ interp_look_up_id(_PyRuntimeState *runtime, int64_t requested_id)
13731373 return NULL ;
13741374}
13751375
1376- /* Return the interpreter state with the given ID.
1377-
1378- Fail with RuntimeError if the interpreter is not found. */
1379-
13801376PyInterpreterState *
1381- _PyInterpreterState_LookUpID (int64_t requested_id )
1377+ _PyInterpreterState_LookUpIDNoErr (int64_t requested_id )
13821378{
13831379 PyInterpreterState * interp = NULL ;
13841380 if (requested_id >= 0 ) {
@@ -1387,6 +1383,18 @@ _PyInterpreterState_LookUpID(int64_t requested_id)
13871383 interp = interp_look_up_id (runtime , requested_id );
13881384 HEAD_UNLOCK (runtime );
13891385 }
1386+ return interp ;
1387+ }
1388+
1389+ /* Return the interpreter state with the given ID.
1390+
1391+ Fail with RuntimeError if the interpreter is not found. */
1392+
1393+ PyInterpreterState *
1394+ _PyInterpreterState_LookUpID (int64_t requested_id )
1395+ {
1396+ assert (_PyThreadState_GET () != NULL );
1397+ PyInterpreterState * interp = _PyInterpreterState_LookUpIDNoErr (requested_id );
13901398 if (interp == NULL && !PyErr_Occurred ()) {
13911399 PyErr_Format (PyExc_InterpreterNotFoundError ,
13921400 "unrecognized interpreter ID %lld" , requested_id );
@@ -1807,13 +1815,23 @@ PyThreadState_Clear(PyThreadState *tstate)
18071815static void
18081816decrement_stoptheworld_countdown (struct _stoptheworld_state * stw );
18091817
1818+ static int
1819+ shutting_down_natives (PyInterpreterState * interp )
1820+ {
1821+ assert (interp != NULL );
1822+ return _Py_atomic_load_int_relaxed (& interp -> threads .finalizing .shutting_down );
1823+ }
1824+
18101825static void
18111826decrement_daemon_count (PyInterpreterState * interp )
18121827{
18131828 assert (interp != NULL );
18141829 struct _Py_finalizing_threads * finalizing = & interp -> threads .finalizing ;
1815- if (_Py_atomic_add_ssize (& finalizing -> countdown , -1 ) == 1 ) {
1830+ Py_ssize_t old = _Py_atomic_add_ssize (& finalizing -> countdown , -1 );
1831+ if (old == 1 && shutting_down_natives (interp )) {
18161832 _PyEvent_Notify (& finalizing -> finished );
1833+ } else if (old <= 0 ) {
1834+ Py_FatalError ("interpreter has negative reference count" );
18171835 }
18181836}
18191837
@@ -3074,6 +3092,9 @@ _PyThreadState_CheckConsistency(PyThreadState *tstate)
30743092int
30753093_PyThreadState_MustExit (PyThreadState * tstate )
30763094{
3095+ if (!tstate -> daemon ) {
3096+ return 0 ;
3097+ }
30773098 int state = _Py_atomic_load_int_relaxed (& tstate -> state );
30783099 return state == _Py_THREAD_SHUTTING_DOWN ;
30793100}
@@ -3221,19 +3242,19 @@ PyInterpreterState_Hold(void)
32213242PyInterpreterState *
32223243PyInterpreterState_Lookup (int64_t interp_id )
32233244{
3224- PyInterpreterState * interp = _PyInterpreterState_LookUpID (interp_id );
3245+ PyInterpreterState * interp = _PyInterpreterState_LookUpIDNoErr (interp_id );
32253246 if (interp == NULL ) {
32263247 return NULL ;
32273248 }
32283249 HEAD_LOCK (& _PyRuntime ); // Prevent deletion
3229- struct _Py_finalizing_threads finalizing = interp -> threads .finalizing ;
3230- PyMutex * mutex = & finalizing . mutex ;
3250+ struct _Py_finalizing_threads * finalizing = & interp -> threads .finalizing ;
3251+ PyMutex * mutex = & finalizing -> mutex ;
32313252 PyMutex_Lock (mutex ); // Synchronize TOCTOU with the event flag
3232- if (_PyEvent_IsSet (& finalizing . finished )) {
3253+ if (_PyEvent_IsSet (& finalizing -> finished )) {
32333254 /* Interpreter has already finished threads */
32343255 interp = NULL ;
32353256 } else {
3236- _Py_atomic_add_ssize (& finalizing . countdown , 1 );
3257+ _Py_atomic_add_ssize (& finalizing -> countdown , 1 );
32373258 }
32383259 PyMutex_Unlock (mutex );
32393260 HEAD_UNLOCK (& _PyRuntime );
0 commit comments