@@ -3548,6 +3548,27 @@ Py_ExitStatusException(PyStatus status)
35483548}
35493549
35503550
3551+ static void
3552+ handle_thread_shutdown_exception (PyThreadState * tstate )
3553+ {
3554+ assert (tstate != NULL );
3555+ assert (_PyErr_Occurred (tstate ));
3556+ PyInterpreterState * interp = tstate -> interp ;
3557+ assert (interp -> threads .head != NULL );
3558+ _PyEval_StopTheWorld (interp );
3559+
3560+ // We don't have to worry about locking this because the
3561+ // world is stopped.
3562+ _Py_FOR_EACH_TSTATE_UNLOCKED (interp , tstate ) {
3563+ if (tstate -> _whence == _PyThreadState_WHENCE_THREADING ) {
3564+ tstate -> _whence = _PyThreadState_WHENCE_THREADING_DAEMON ;
3565+ }
3566+ }
3567+
3568+ _PyEval_StartTheWorld (interp );
3569+ PyErr_FormatUnraisable ("Exception ignored on threading shutdown" );
3570+ }
3571+
35513572/* Wait until threading._shutdown completes, provided
35523573 the threading module was imported in the first place.
35533574 The shutdown routine will wait until all non-daemon
@@ -3559,14 +3580,14 @@ wait_for_thread_shutdown(PyThreadState *tstate)
35593580 PyObject * threading = PyImport_GetModule (& _Py_ID (threading ));
35603581 if (threading == NULL ) {
35613582 if (_PyErr_Occurred (tstate )) {
3562- PyErr_FormatUnraisable ( "Exception ignored on threading shutdown" );
3583+ handle_thread_shutdown_exception ( tstate );
35633584 }
35643585 /* else: threading not imported */
35653586 return ;
35663587 }
35673588 result = PyObject_CallMethodNoArgs (threading , & _Py_ID (_shutdown ));
35683589 if (result == NULL ) {
3569- PyErr_FormatUnraisable ( "Exception ignored on threading shutdown" );
3590+ handle_thread_shutdown_exception ( tstate );
35703591 }
35713592 else {
35723593 Py_DECREF (result );
0 commit comments