mirror of https://github.com/python/cpython.git
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:
parent
2294bfc19d
commit
5c14e6498a
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue