@@ -196,8 +196,7 @@ tstate_must_exit(PyThreadState *tstate)
196196 tstate->interp->runtime to support calls from Python daemon threads.
197197 After Py_Finalize() has been called, tstate can be a dangling pointer:
198198 point to PyThreadState freed memory. */
199- _PyRuntimeState * runtime = & _PyRuntime ;
200- PyThreadState * finalizing = _PyRuntimeState_GetFinalizing (runtime );
199+ PyThreadState * finalizing = _PyRuntimeState_GetFinalizing (& _PyRuntime );
201200 return (finalizing != NULL && finalizing != tstate );
202201}
203202
@@ -243,20 +242,23 @@ take_gil(PyThreadState *tstate)
243242 }
244243
245244 while (_Py_atomic_load_relaxed (& gil -> locked )) {
246- int timed_out = 0 ;
247- unsigned long saved_switchnum ;
248-
249- saved_switchnum = gil -> switch_number ;
250-
245+ unsigned long saved_switchnum = gil -> switch_number ;
251246
252247 unsigned long interval = (gil -> interval >= 1 ? gil -> interval : 1 );
248+ int timed_out = 0 ;
253249 COND_TIMED_WAIT (gil -> cond , gil -> mutex , interval , timed_out );
250+
254251 /* If we timed out and no switch occurred in the meantime, it is time
255252 to ask the GIL-holding thread to drop it. */
256253 if (timed_out &&
257254 _Py_atomic_load_relaxed (& gil -> locked ) &&
258255 gil -> switch_number == saved_switchnum )
259256 {
257+ if (tstate_must_exit (tstate )) {
258+ MUTEX_UNLOCK (gil -> mutex );
259+ PyThread_exit_thread ();
260+ }
261+
260262 SET_GIL_DROP_REQUEST (ceval );
261263 }
262264 }
@@ -281,6 +283,19 @@ take_gil(PyThreadState *tstate)
281283 MUTEX_UNLOCK (gil -> switch_mutex );
282284#endif
283285
286+ if (tstate_must_exit (tstate )) {
287+ /* bpo-36475: If Py_Finalize() has been called and tstate is not
288+ the thread which called Py_Finalize(), exit immediately the
289+ thread.
290+
291+ This code path can be reached by a daemon thread which was waiting
292+ in take_gil() while the main thread called
293+ wait_for_thread_shutdown() from Py_Finalize(). */
294+ MUTEX_UNLOCK (gil -> mutex );
295+ drop_gil (ceval , ceval2 , tstate );
296+ PyThread_exit_thread ();
297+ }
298+
284299 if (_Py_atomic_load_relaxed (& ceval -> gil_drop_request )) {
285300 RESET_GIL_DROP_REQUEST (ceval , ceval2 );
286301 }
@@ -293,27 +308,13 @@ take_gil(PyThreadState *tstate)
293308 COMPUTE_EVAL_BREAKER (ceval , ceval2 );
294309 }
295310
296- int must_exit = tstate_must_exit (tstate );
297-
298311 /* Don't access tstate if the thread must exit */
299- if (! must_exit && tstate -> async_exc != NULL ) {
312+ if (tstate -> async_exc != NULL ) {
300313 _PyEval_SignalAsyncExc (tstate );
301314 }
302315
303316 MUTEX_UNLOCK (gil -> mutex );
304317
305- if (must_exit ) {
306- /* bpo-36475: If Py_Finalize() has been called and tstate is not
307- the thread which called Py_Finalize(), exit immediately the
308- thread.
309-
310- This code path can be reached by a daemon thread which was waiting
311- in take_gil() while the main thread called
312- wait_for_thread_shutdown() from Py_Finalize(). */
313- drop_gil (ceval , ceval2 , tstate );
314- PyThread_exit_thread ();
315- }
316-
317318 errno = err ;
318319}
319320
0 commit comments