@@ -277,12 +277,15 @@ drop_gil(PyInterpreterState *interp, PyThreadState *tstate, int final_release)
277277
278278/* Take the GIL.
279279
280+ Return 0 on success.
281+ Return -1 if the thread must exit.
282+
280283 The function saves errno at entry and restores its value at exit.
281284 It may hang rather than return if the interpreter has been finalized.
282285
283286 tstate must be non-NULL. */
284- static void
285- take_gil (PyThreadState * tstate )
287+ static int
288+ take_gil_or_fail (PyThreadState * tstate )
286289{
287290 int err = errno ;
288291
@@ -304,15 +307,15 @@ take_gil(PyThreadState *tstate)
304307 C++. gh-87135: The best that can be done is to hang the thread as
305308 the public APIs calling this have no error reporting mechanism (!).
306309 */
307- PyThread_hang_thread () ;
310+ goto tstate_must_exit ;
308311 }
309312
310313 assert (_PyThreadState_CheckConsistency (tstate ));
311314 PyInterpreterState * interp = tstate -> interp ;
312315 struct _gil_runtime_state * gil = interp -> ceval .gil ;
313316#ifdef Py_GIL_DISABLED
314317 if (!_Py_atomic_load_int_relaxed (& gil -> enabled )) {
315- return ;
318+ goto done ;
316319 }
317320#endif
318321
@@ -348,9 +351,7 @@ take_gil(PyThreadState *tstate)
348351 if (drop_requested ) {
349352 _Py_unset_eval_breaker_bit (holder_tstate , _PY_GIL_DROP_REQUEST_BIT );
350353 }
351- // gh-87135: hang the thread as *thread_exit() is not a safe
352- // API. It lacks stack unwind and local variable destruction.
353- PyThread_hang_thread ();
354+ goto tstate_must_exit ;
354355 }
355356 assert (_PyThreadState_CheckConsistency (tstate ));
356357
@@ -366,7 +367,7 @@ take_gil(PyThreadState *tstate)
366367 // return.
367368 COND_SIGNAL (gil -> cond );
368369 MUTEX_UNLOCK (gil -> mutex );
369- return ;
370+ goto done ;
370371 }
371372#endif
372373
@@ -401,7 +402,7 @@ take_gil(PyThreadState *tstate)
401402 /* tstate could be a dangling pointer, so don't pass it to
402403 drop_gil(). */
403404 drop_gil (interp , NULL , 1 );
404- PyThread_hang_thread () ;
405+ goto tstate_must_exit ;
405406 }
406407 assert (_PyThreadState_CheckConsistency (tstate ));
407408
@@ -411,8 +412,25 @@ take_gil(PyThreadState *tstate)
411412
412413 MUTEX_UNLOCK (gil -> mutex );
413414
415+ #ifdef Py_GIL_DISABLED
416+ done :
417+ #endif
414418 errno = err ;
415- return ;
419+ return 0 ;
420+
421+ tstate_must_exit :
422+ errno = err ;
423+ return -1 ;
424+ }
425+
426+ static void
427+ take_gil (PyThreadState * tstate )
428+ {
429+ if (take_gil_or_fail (tstate ) < 0 ) {
430+ // gh-87135: hang the thread as *thread_exit() is not a safe
431+ // API. It lacks stack unwind and local variable destruction.
432+ PyThread_hang_thread ();
433+ }
416434}
417435
418436void _PyEval_SetSwitchInterval (unsigned long microseconds )
@@ -586,6 +604,13 @@ _PyEval_AcquireLock(PyThreadState *tstate)
586604 take_gil (tstate );
587605}
588606
607+ int
608+ _PyEval_AcquireLockOrFail (PyThreadState * tstate )
609+ {
610+ _Py_EnsureTstateNotNULL (tstate );
611+ return take_gil_or_fail (tstate );
612+ }
613+
589614void
590615_PyEval_ReleaseLock (PyInterpreterState * interp ,
591616 PyThreadState * tstate ,
@@ -641,19 +666,32 @@ PyEval_SaveThread(void)
641666 return tstate ;
642667}
643668
644- void
645- PyEval_RestoreThread (PyThreadState * tstate )
669+
670+ int
671+ _PyEval_RestoreThreadOrFail (PyThreadState * tstate )
646672{
647673#ifdef MS_WINDOWS
648674 int err = GetLastError ();
649675#endif
650676
651677 _Py_EnsureTstateNotNULL (tstate );
652- _PyThreadState_Attach (tstate );
678+ if (_PyThreadState_AttachOrFail (tstate ) < 0 ) {
679+ return -1 ;
680+ }
653681
654682#ifdef MS_WINDOWS
655683 SetLastError (err );
656684#endif
685+ return 0 ;
686+ }
687+
688+
689+ void
690+ PyEval_RestoreThread (PyThreadState * tstate )
691+ {
692+ if (_PyEval_RestoreThreadOrFail (tstate ) < 0 ) {
693+ PyThread_hang_thread ();
694+ }
657695}
658696
659697
0 commit comments