Skip to content

Commit

Permalink
Don't drop the GIL during thread deletion unless the current thread h…
Browse files Browse the repository at this point in the history
…olds it
  • Loading branch information
swtaarrs committed May 7, 2024
1 parent 4605465 commit c102cef
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 5 deletions.
5 changes: 1 addition & 4 deletions Lib/test/test_importlib/test_threaded_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from test.support import verbose
from test.support.import_helper import forget, mock_register_at_fork
from test.support.os_helper import (TESTFN, unlink, rmtree)
from test.support import script_helper, threading_helper, requires_gil_enabled
from test.support import script_helper, threading_helper

threading_helper.requires_working_threading(module=True)

Expand Down Expand Up @@ -248,9 +248,6 @@ def test_concurrent_futures_circular_import(self):
'partial', 'cfimport.py')
script_helper.assert_python_ok(fn)

# gh-118727 and gh-118729: pool_in_threads.py may crash in free-threaded
# builds, which can hang the Tsan test so temporarily skip it for now.
@requires_gil_enabled("gh-118727: test may crash in free-threaded builds")
def test_multiprocessing_pool_circular_import(self):
# Regression test for bpo-41567
fn = os.path.join(os.path.dirname(__file__),
Expand Down
14 changes: 13 additions & 1 deletion Python/pystate.c
Original file line number Diff line number Diff line change
Expand Up @@ -1831,10 +1831,22 @@ _PyThreadState_DeleteCurrent(PyThreadState *tstate)
_Py_EnsureTstateNotNULL(tstate);
#ifdef Py_GIL_DISABLED
_Py_qsbr_detach(((_PyThreadStateImpl *)tstate)->qsbr);
// tstate_delete_common() removes tstate from the tracking used by the
// stop-the-world machinery. This means that another thread could enable
// the GIL before our call to _PyEval_ReleaseLock(), violating its
// assumption that its only called by an attached thread that holds the GIL
// if and only if the GIL is enabled. Work around this by deciding if we
// need to release the GIL while our thread is still considered for
// stop-the-world.
int holds_gil = _PyEval_IsGILEnabled(tstate);
#else
int holds_gil = 1;
#endif
current_fast_clear(tstate->interp->runtime);
tstate_delete_common(tstate);
_PyEval_ReleaseLock(tstate->interp, NULL);
if (holds_gil) {
_PyEval_ReleaseLock(tstate->interp, NULL);
}
free_threadstate((_PyThreadStateImpl *)tstate);
}

Expand Down

0 comments on commit c102cef

Please sign in to comment.