mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
bpo-20891: Fix PyGILState_Ensure() (#4650)
When PyGILState_Ensure() is called in a non-Python thread before PyEval_InitThreads(), only call PyEval_InitThreads() after calling PyThreadState_New() to fix a crash. Add an unit test in test_embed.
This commit is contained in:
parent
986375ebde
commit
b4d1e1f7c1
5 changed files with 83 additions and 8 deletions
|
@ -922,6 +922,8 @@ PyGILState_Ensure(void)
|
|||
{
|
||||
int current;
|
||||
PyThreadState *tcur;
|
||||
int need_init_threads = 0;
|
||||
|
||||
/* Note that we do not auto-init Python here - apart from
|
||||
potential races with 2 threads auto-initializing, pep-311
|
||||
spells out other issues. Embedders are expected to have
|
||||
|
@ -929,12 +931,10 @@ PyGILState_Ensure(void)
|
|||
*/
|
||||
/* Py_Initialize() hasn't been called! */
|
||||
assert(_PyRuntime.gilstate.autoInterpreterState);
|
||||
|
||||
tcur = (PyThreadState *)PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey);
|
||||
if (tcur == NULL) {
|
||||
/* At startup, Python has no concrete GIL. If PyGILState_Ensure() is
|
||||
called from a new thread for the first time, we need the create the
|
||||
GIL. */
|
||||
PyEval_InitThreads();
|
||||
need_init_threads = 1;
|
||||
|
||||
/* Create a new thread state for this thread */
|
||||
tcur = PyThreadState_New(_PyRuntime.gilstate.autoInterpreterState);
|
||||
|
@ -945,16 +945,28 @@ PyGILState_Ensure(void)
|
|||
tcur->gilstate_counter = 0;
|
||||
current = 0; /* new thread state is never current */
|
||||
}
|
||||
else
|
||||
else {
|
||||
current = PyThreadState_IsCurrent(tcur);
|
||||
if (current == 0)
|
||||
}
|
||||
|
||||
if (current == 0) {
|
||||
PyEval_RestoreThread(tcur);
|
||||
}
|
||||
|
||||
/* Update our counter in the thread-state - no need for locks:
|
||||
- tcur will remain valid as we hold the GIL.
|
||||
- the counter is safe as we are the only thread "allowed"
|
||||
to modify this value
|
||||
*/
|
||||
++tcur->gilstate_counter;
|
||||
|
||||
if (need_init_threads) {
|
||||
/* At startup, Python has no concrete GIL. If PyGILState_Ensure() is
|
||||
called from a new thread for the first time, we need the create the
|
||||
GIL. */
|
||||
PyEval_InitThreads();
|
||||
}
|
||||
|
||||
return current ? PyGILState_LOCKED : PyGILState_UNLOCKED;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue