@@ -119,6 +119,8 @@ _Py_brc_merge_refcounts(PyThreadState *tstate)
119119 struct _brc_thread_state * brc = & ((_PyThreadStateImpl * )tstate )-> brc ;
120120 struct _brc_bucket * bucket = get_bucket (tstate -> interp , brc -> tid );
121121
122+ assert (brc -> tid == _Py_ThreadId ());
123+
122124 // Append all objects into a local stack. We don't want to hold the lock
123125 // while calling destructors.
124126 PyMutex_Lock (& bucket -> mutex );
@@ -142,11 +144,12 @@ void
142144_Py_brc_init_thread (PyThreadState * tstate )
143145{
144146 struct _brc_thread_state * brc = & ((_PyThreadStateImpl * )tstate )-> brc ;
145- brc -> tid = _Py_ThreadId ();
147+ uintptr_t tid = _Py_ThreadId ();
146148
147149 // Add ourself to the hashtable
148- struct _brc_bucket * bucket = get_bucket (tstate -> interp , brc -> tid );
150+ struct _brc_bucket * bucket = get_bucket (tstate -> interp , tid );
149151 PyMutex_Lock (& bucket -> mutex );
152+ brc -> tid = tid ;
150153 llist_insert_tail (& bucket -> root , & brc -> bucket_node );
151154 PyMutex_Unlock (& bucket -> mutex );
152155}
@@ -155,6 +158,13 @@ void
155158_Py_brc_remove_thread (PyThreadState * tstate )
156159{
157160 struct _brc_thread_state * brc = & ((_PyThreadStateImpl * )tstate )-> brc ;
161+ if (brc -> tid == 0 ) {
162+ // The thread state may have been created, but never bound to a native
163+ // thread and therefore never added to the hashtable.
164+ assert (tstate -> _status .bound == 0 );
165+ return ;
166+ }
167+
158168 struct _brc_bucket * bucket = get_bucket (tstate -> interp , brc -> tid );
159169
160170 // We need to fully process any objects to merge before removing ourself
0 commit comments