This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author vstinner
Recipients eric.snow, pablogsal, pitrou, vstinner
Date 2019-06-10.21:57:27
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <>
threading._shutdown() uses threading.enumerate() which iterations on threading._active.

threading.Thread registers itself into threading._active using its _bootstrap_inner() method. It unregisters itself when _bootstrap_inner() completes, whereas its is_alive() method still returns true: since the underlying native thread still runs and the Python thread state still exists.

_thread._set_sentinel() creates a lock and registers a tstate->on_delete callback to release this lock. It's called by threading.Thread._set_tstate_lock() to set threading.Thread._tstate_lock. This lock is used by threading.Thread.join() to wait until the thread completes.

_thread.start_new_thread() calls the C function t_bootstrap() which ends with:


_PyThreadState_DeleteCurrent() calls tstate->on_delete() which releases threading.Thread._tstate_lock lock.

In test_threads_join_2() test, PyThreadState_Clear() blocks on clearing thread variables: the Sleeper destructor of the Sleeper instance sleeps.

The race condition is that:

* threading._shutdown() rely on threading._alive
* Py_EndInterpreter() rely on the interpreter linked list of Python thread states: interp->tstate_head.
Date User Action Args
2019-06-10 21:57:27vstinnersetrecipients: + vstinner, pitrou, eric.snow, pablogsal
2019-06-10 21:57:27vstinnersetmessageid: <>
2019-06-10 21:57:27vstinnerlinkissue36402 messages
2019-06-10 21:57:27vstinnercreate