diff options
author | Brett Simmers <swtaarrs@users.noreply.github.com> | 2024-05-23 20:59:35 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-23 20:59:35 (GMT) |
commit | be1dfccdf2c5c7671b8a549e969b8cf7d60d9936 (patch) | |
tree | 920d35829b0fb8d51399ff69760998165da704cb /Python/pystate.c | |
parent | b30d30c747df2bf9f1614df8e76db2ffdb24fcd8 (diff) | |
download | cpython-be1dfccdf2c5c7671b8a549e969b8cf7d60d9936.zip cpython-be1dfccdf2c5c7671b8a549e969b8cf7d60d9936.tar.gz cpython-be1dfccdf2c5c7671b8a549e969b8cf7d60d9936.tar.bz2 |
gh-118727: Don't drop the GIL in `drop_gil()` unless the current thread holds it (#118745)
`drop_gil()` assumes that its caller is attached, which means that the current
thread holds the GIL if and only if the GIL is enabled, and the enabled-state
of the GIL won't change. This isn't true, though, because `detach_thread()`
calls `_PyEval_ReleaseLock()` after detaching and
`_PyThreadState_DeleteCurrent()` calls it after removing the current thread
from consideration for stop-the-world requests (effectively detaching it).
Fix this by remembering whether or not a thread acquired the GIL when it last
attached, in `PyThreadState._status.holds_gil`, and check this in `drop_gil()`
instead of `gil->enabled`.
This fixes a crash in `test_multiprocessing_pool_circular_import()`, so I've
reenabled it.
Diffstat (limited to 'Python/pystate.c')
-rw-r--r-- | Python/pystate.c | 11 |
1 files changed, 4 insertions, 7 deletions
diff --git a/Python/pystate.c b/Python/pystate.c index 0832b37..1ea1ad9 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1843,7 +1843,7 @@ _PyThreadState_DeleteCurrent(PyThreadState *tstate) #endif current_fast_clear(tstate->interp->runtime); tstate_delete_common(tstate); - _PyEval_ReleaseLock(tstate->interp, NULL); + _PyEval_ReleaseLock(tstate->interp, tstate, 1); free_threadstate((_PyThreadStateImpl *)tstate); } @@ -2068,7 +2068,7 @@ _PyThreadState_Attach(PyThreadState *tstate) while (1) { - int acquired_gil = _PyEval_AcquireLock(tstate); + _PyEval_AcquireLock(tstate); // XXX assert(tstate_is_alive(tstate)); current_fast_set(&_PyRuntime, tstate); @@ -2079,20 +2079,17 @@ _PyThreadState_Attach(PyThreadState *tstate) } #ifdef Py_GIL_DISABLED - if (_PyEval_IsGILEnabled(tstate) != acquired_gil) { + if (_PyEval_IsGILEnabled(tstate) && !tstate->_status.holds_gil) { // The GIL was enabled between our call to _PyEval_AcquireLock() // and when we attached (the GIL can't go from enabled to disabled // here because only a thread holding the GIL can disable // it). Detach and try again. - assert(!acquired_gil); tstate_set_detached(tstate, _Py_THREAD_DETACHED); tstate_deactivate(tstate); current_fast_clear(&_PyRuntime); continue; } _Py_qsbr_attach(((_PyThreadStateImpl *)tstate)->qsbr); -#else - (void)acquired_gil; #endif break; } @@ -2123,7 +2120,7 @@ detach_thread(PyThreadState *tstate, int detached_state) tstate_deactivate(tstate); tstate_set_detached(tstate, detached_state); current_fast_clear(&_PyRuntime); - _PyEval_ReleaseLock(tstate->interp, tstate); + _PyEval_ReleaseLock(tstate->interp, tstate, 0); } void |