@@ -36,6 +36,12 @@ static PyThread_type_lock head_mutex = NULL; /* Protects interp->tstate_head */
3636#define HEAD_INIT () (void)(head_mutex || (head_mutex = PyThread_allocate_lock()))
3737#define HEAD_LOCK () PyThread_acquire_lock(head_mutex, WAIT_LOCK)
3838#define HEAD_UNLOCK () PyThread_release_lock(head_mutex)
39+
40+ /* The single PyInterpreterState used by this process'
41+ GILState implementation
42+ */
43+ static PyInterpreterState * autoInterpreterState = NULL ;
44+ static int autoTLSkey = 0 ;
3945#else
4046#define HEAD_INIT () /* Nothing */
4147#define HEAD_LOCK () /* Nothing */
@@ -47,6 +53,8 @@ static PyInterpreterState *interp_head = NULL;
4753PyThreadState * _PyThreadState_Current = NULL ;
4854PyThreadFrameGetter _PyThreadState_GetFrame = NULL ;
4955
56+ static void _PyGILState_NoteThreadState (PyThreadState * tstate );
57+
5058
5159PyInterpreterState *
5260PyInterpreterState_New (void )
@@ -180,6 +188,8 @@ PyThreadState_New(PyInterpreterState *interp)
180188 tstate -> c_profileobj = NULL ;
181189 tstate -> c_traceobj = NULL ;
182190
191+ _PyGILState_NoteThreadState (tstate );
192+
183193 HEAD_LOCK ();
184194 tstate -> next = interp -> tstate_head ;
185195 interp -> tstate_head = tstate ;
@@ -261,6 +271,8 @@ PyThreadState_DeleteCurrent()
261271 "PyThreadState_DeleteCurrent: no current tstate" );
262272 _PyThreadState_Current = NULL ;
263273 tstate_delete_common (tstate );
274+ if (autoTLSkey && PyThread_get_key_value (autoTLSkey ) == tstate )
275+ PyThread_delete_key_value (autoTLSkey );
264276 PyEval_ReleaseLock ();
265277}
266278#endif /* WITH_THREAD */
@@ -393,12 +405,6 @@ PyThreadState_IsCurrent(PyThreadState *tstate)
393405 return tstate == _PyThreadState_Current ;
394406}
395407
396- /* The single PyInterpreterState used by this process'
397- GILState implementation
398- */
399- static PyInterpreterState * autoInterpreterState = NULL ;
400- static int autoTLSkey = 0 ;
401-
402408/* Internal initialization/finalization functions called by
403409 Py_Initialize/Py_Finalize
404410*/
@@ -408,12 +414,10 @@ _PyGILState_Init(PyInterpreterState *i, PyThreadState *t)
408414 assert (i && t ); /* must init with valid states */
409415 autoTLSkey = PyThread_create_key ();
410416 autoInterpreterState = i ;
411- /* Now stash the thread state for this thread in TLS */
412417 assert (PyThread_get_key_value (autoTLSkey ) == NULL );
413- if (PyThread_set_key_value (autoTLSkey , (void * )t ) < 0 )
414- Py_FatalError ("Couldn't create autoTLSkey mapping" );
415- assert (t -> gilstate_counter == 0 ); /* must be a new thread state */
416- t -> gilstate_counter = 1 ;
418+ assert (t -> gilstate_counter == 0 );
419+
420+ _PyGILState_NoteThreadState (t );
417421}
418422
419423void
@@ -424,6 +428,41 @@ _PyGILState_Fini(void)
424428 autoInterpreterState = NULL ;;
425429}
426430
431+ /* When a thread state is created for a thread by some mechanism other than
432+ PyGILState_Ensure, it's important that the GILState machinery knows about
433+ it so it doesn't try to create another thread state for the thread (this is
434+ a better fix for SF bug #1010677 than the first one attempted).
435+ */
436+ void
437+ _PyGILState_NoteThreadState (PyThreadState * tstate )
438+ {
439+ /* If autoTLSkey is 0, this must be the very first threadstate created
440+ in Py_Initialize(). Don't do anything for now (we'll be back here
441+ when _PyGILState_Init is called). */
442+ if (!autoTLSkey )
443+ return ;
444+
445+ /* Stick the thread state for this thread in thread local storage.
446+
447+ The only situation where you can legitimately have more than one
448+ thread state for an OS level thread is when there are multiple
449+ interpreters, when:
450+
451+ a) You shouldn't really be using the PyGILState_ APIs anyway,
452+ and:
453+
454+ b) The slightly odd way PyThread_set_key_value works (see
455+ comments by its implementation) means that the first thread
456+ state created for that given OS level thread will "win",
457+ which seems reasonable behaviour.
458+ */
459+ if (PyThread_set_key_value (autoTLSkey , (void * )tstate ) < 0 )
460+ Py_FatalError ("Couldn't create autoTLSkey mapping" );
461+
462+ /* PyGILState_Release must not try to delete this thread state. */
463+ tstate -> gilstate_counter = 1 ;
464+ }
465+
427466/* The public functions */
428467PyThreadState *
429468PyGILState_GetThisThreadState (void )
@@ -450,8 +489,9 @@ PyGILState_Ensure(void)
450489 tcur = PyThreadState_New (autoInterpreterState );
451490 if (tcur == NULL )
452491 Py_FatalError ("Couldn't create thread-state for new thread" );
453- if (PyThread_set_key_value (autoTLSkey , (void * )tcur ) < 0 )
454- Py_FatalError ("Couldn't create autoTLSkey mapping" );
492+ /* This is our thread state! We'll need to delete it in the
493+ matching call to PyGILState_Release(). */
494+ tcur -> gilstate_counter = 0 ;
455495 current = 0 ; /* new thread state is never current */
456496 }
457497 else
@@ -498,8 +538,6 @@ PyGILState_Release(PyGILState_STATE oldstate)
498538 * habit of coming back).
499539 */
500540 PyThreadState_DeleteCurrent ();
501- /* Delete this thread from our TLS. */
502- PyThread_delete_key_value (autoTLSkey );
503541 }
504542 /* Release the lock if necessary */
505543 else if (oldstate == PyGILState_UNLOCKED )
0 commit comments