diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2017-11-30 22:05:00 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-30 22:05:00 +0100 |
commit | b4d1e1f7c1af6ae33f0e371576c8bcafedb099db (patch) | |
tree | 857873eca2c22a51524b53fb54e30ea9f66f66d7 /Python/pystate.c | |
parent | 986375ebde0dd5ff2b7349e445a06bd28a3a8ee2 (diff) | |
download | cpython-git-b4d1e1f7c1af6ae33f0e371576c8bcafedb099db.tar.gz |
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.
Diffstat (limited to 'Python/pystate.c')
-rw-r--r-- | Python/pystate.c | 24 |
1 files changed, 18 insertions, 6 deletions
diff --git a/Python/pystate.c b/Python/pystate.c index 0fb8ed0719..500f967687 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -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; } |