PyGILState_Release(): If we need to delete the TLS entry for this thread,

that must be done under protection of the GIL, for reasons explained in
new comments.
This commit is contained in:
Tim Peters 2004-10-09 23:55:36 +00:00
parent 2294bfc19d
commit 5c14e6498a
1 changed files with 15 additions and 8 deletions

View File

@ -472,24 +472,31 @@ PyGILState_Release(PyGILState_STATE oldstate)
assert(tcur->gilstate_counter >= 0); /* illegal counter value */ assert(tcur->gilstate_counter >= 0); /* illegal counter value */
/* If we are about to destroy this thread-state, we must /* If we are about to destroy this thread-state, we must
clear it while the lock is held, as destructors may run * clear it while the lock is held, as destructors may run.
* In addition, we have to delete out TLS entry, which is keyed
* by thread id, while the GIL is held: the thread calling us may
* go away, and a new thread may be created with the same thread
* id. If we don't delete our TLS until after the GIL is released,
* that new thread may manage to insert a TLS value with the same
* thread id as ours, and then we'd erroneously delete it.
*/ */
if (tcur->gilstate_counter == 0) { if (tcur->gilstate_counter == 0) {
/* can't have been locked when we created it */ /* can't have been locked when we created it */
assert(oldstate == PyGILState_UNLOCKED); assert(oldstate == PyGILState_UNLOCKED);
PyThreadState_Clear(tcur); PyThreadState_Clear(tcur);
/* Delete this thread from our TLS */
PyThread_delete_key_value(autoTLSkey);
} }
/* Release the lock if necessary */ /* Release the lock if necessary */
if (oldstate == PyGILState_UNLOCKED) if (oldstate == PyGILState_UNLOCKED)
PyEval_ReleaseThread(tcur); PyEval_ReleaseThread(tcur);
/* Now complete destruction of the thread if necessary */ /* Now complete destruction of the thread if necessary. This
if (tcur->gilstate_counter == 0) { * couldn't be done before PyEval_ReleaseThread() because
/* Delete this thread from our TLS */ * PyThreadState_Delete doesn't allow deleting the current thread.
PyThread_delete_key_value(autoTLSkey); */
/* Delete the thread-state */ if (tcur->gilstate_counter == 0)
PyThreadState_Delete(tcur); PyThreadState_Delete(tcur);
} }
}
#endif /* WITH_THREAD */ #endif /* WITH_THREAD */