@@ -159,6 +159,8 @@ static void bind_gilstate_tstate(PyThreadState *);
159159static void unbind_gilstate_tstate (PyThreadState * );
160160
161161static void tstate_mimalloc_bind (PyThreadState * );
162+ static void add_threadstate (PyInterpreterState * interp , PyThreadState * tstate ,
163+ PyThreadState * next );
162164
163165static void
164166bind_tstate (PyThreadState * tstate )
@@ -190,6 +192,18 @@ bind_tstate(PyThreadState *tstate)
190192 tstate_mimalloc_bind (tstate );
191193
192194 tstate -> _status .bound = 1 ;
195+
196+ // Publish the thread state to the interpreter's thread list only now
197+ // that it is fully initialized, so that readers of the list never see
198+ // a partially initialized thread state.
199+ PyInterpreterState * interp = tstate -> interp ;
200+ HEAD_LOCK (interp -> runtime );
201+ if (interp -> stoptheworld .requested || _PyRuntime .stoptheworld .requested ) {
202+ // Start in the suspended state if there is an ongoing stop-the-world.
203+ tstate -> state = _Py_THREAD_SUSPENDED ;
204+ }
205+ add_threadstate (interp , tstate , interp -> threads .head );
206+ HEAD_UNLOCK (interp -> runtime );
193207}
194208
195209static void
@@ -1638,10 +1652,6 @@ init_threadstate(_PyThreadStateImpl *_tstate,
16381652
16391653 llist_init (& _tstate -> mem_free_queue );
16401654 llist_init (& _tstate -> asyncio_tasks_head );
1641- if (interp -> stoptheworld .requested || _PyRuntime .stoptheworld .requested ) {
1642- // Start in the suspended state if there is an ongoing stop-the-world.
1643- tstate -> state = _Py_THREAD_SUSPENDED ;
1644- }
16451655
16461656 tstate -> _status .initialized = 1 ;
16471657}
@@ -1699,10 +1709,6 @@ new_threadstate(PyInterpreterState *interp, int whence)
16991709 uint64_t id = interp -> threads .next_unique_id ;
17001710 init_threadstate (tstate , interp , id , whence );
17011711
1702- // Add the new thread state to the interpreter.
1703- PyThreadState * old_head = interp -> threads .head ;
1704- add_threadstate (interp , (PyThreadState * )tstate , old_head );
1705-
17061712 HEAD_UNLOCK (interp -> runtime );
17071713
17081714#ifdef Py_GIL_DISABLED
@@ -1930,24 +1936,33 @@ tstate_delete_common(PyThreadState *tstate, int release_gil)
19301936 _PyRuntimeState * runtime = interp -> runtime ;
19311937
19321938 HEAD_LOCK (runtime );
1933- if (tstate -> prev ) {
1934- tstate -> prev -> next = tstate -> next ;
1935- }
1936- else {
1937- interp -> threads .head = tstate -> next ;
1938- }
1939- if (tstate -> next ) {
1940- tstate -> next -> prev = tstate -> prev ;
1941- }
1942- if (tstate -> state != _Py_THREAD_SUSPENDED ) {
1943- // Any ongoing stop-the-world request should not wait for us because
1944- // our thread is getting deleted.
1945- if (interp -> stoptheworld .requested ) {
1946- decrement_stoptheworld_countdown (& interp -> stoptheworld );
1939+ if (tstate -> _status .bound ) {
1940+ if (tstate -> prev ) {
1941+ tstate -> prev -> next = tstate -> next ;
19471942 }
1948- if (runtime -> stoptheworld .requested ) {
1949- decrement_stoptheworld_countdown (& runtime -> stoptheworld );
1943+ else {
1944+ interp -> threads .head = tstate -> next ;
1945+ }
1946+ if (tstate -> next ) {
1947+ tstate -> next -> prev = tstate -> prev ;
19501948 }
1949+ if (tstate -> state != _Py_THREAD_SUSPENDED ) {
1950+ // Any ongoing stop-the-world request should not wait for us
1951+ // because our thread is getting deleted.
1952+ if (interp -> stoptheworld .requested ) {
1953+ decrement_stoptheworld_countdown (& interp -> stoptheworld );
1954+ }
1955+ if (runtime -> stoptheworld .requested ) {
1956+ decrement_stoptheworld_countdown (& runtime -> stoptheworld );
1957+ }
1958+ }
1959+ }
1960+ else {
1961+ // The thread state was never bound, so it was never added to the
1962+ // interpreter's thread list and no stop-the-world request is
1963+ // waiting on it.
1964+ assert (tstate -> prev == NULL && tstate -> next == NULL );
1965+ assert (interp -> threads .head != tstate );
19511966 }
19521967
19531968#if defined(Py_REF_DEBUG ) && defined(Py_GIL_DISABLED )
0 commit comments