mirror of
https://github.com/python/cpython.git
synced 2025-08-23 10:16:01 +00:00
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.
This commit is contained in:
parent
b30d30c747
commit
be1dfccdf2
5 changed files with 73 additions and 60 deletions
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue