diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2024-06-06 18:03:01 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-06 18:03:01 (GMT) |
commit | 517733ce3cd7937dc527f1f191582c21cfb9b685 (patch) | |
tree | 64e0f07217be36c2991f65c8d9cd6c02114d5c68 /Modules | |
parent | 015ddfeca5e39a3796ee144d07accb1d5c7e7522 (diff) | |
download | cpython-517733ce3cd7937dc527f1f191582c21cfb9b685.zip cpython-517733ce3cd7937dc527f1f191582c21cfb9b685.tar.gz cpython-517733ce3cd7937dc527f1f191582c21cfb9b685.tar.bz2 |
[3.13] gh-117657: Fix TSAN race involving import lock (GH-118523) (#120169)
This adds a `_PyRecursiveMutex` type based on `PyMutex` and uses that
for the import lock. This fixes some data races in the free-threaded
build and generally simplifies the import lock code.
(cherry picked from commit e21057b99967eb5323320e6d1121955e0cd2985e)
Co-authored-by: Sam Gross <colesbury@gmail.com>
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_testinternalcapi/test_lock.c | 25 | ||||
-rw-r--r-- | Modules/posixmodule.c | 11 |
2 files changed, 27 insertions, 9 deletions
diff --git a/Modules/_testinternalcapi/test_lock.c b/Modules/_testinternalcapi/test_lock.c index 4900459..1544fe1 100644 --- a/Modules/_testinternalcapi/test_lock.c +++ b/Modules/_testinternalcapi/test_lock.c @@ -2,6 +2,7 @@ #include "parts.h" #include "pycore_lock.h" +#include "pycore_pythread.h" // PyThread_get_thread_ident_ex() #include "clinic/test_lock.c.h" @@ -476,6 +477,29 @@ test_lock_rwlock(PyObject *self, PyObject *obj) Py_RETURN_NONE; } +static PyObject * +test_lock_recursive(PyObject *self, PyObject *obj) +{ + _PyRecursiveMutex m = (_PyRecursiveMutex){0}; + assert(!_PyRecursiveMutex_IsLockedByCurrentThread(&m)); + + _PyRecursiveMutex_Lock(&m); + assert(m.thread == PyThread_get_thread_ident_ex()); + assert(PyMutex_IsLocked(&m.mutex)); + assert(m.level == 0); + + _PyRecursiveMutex_Lock(&m); + assert(m.level == 1); + _PyRecursiveMutex_Unlock(&m); + + _PyRecursiveMutex_Unlock(&m); + assert(m.thread == 0); + assert(!PyMutex_IsLocked(&m.mutex)); + assert(m.level == 0); + + Py_RETURN_NONE; +} + static PyMethodDef test_methods[] = { {"test_lock_basic", test_lock_basic, METH_NOARGS}, {"test_lock_two_threads", test_lock_two_threads, METH_NOARGS}, @@ -485,6 +509,7 @@ static PyMethodDef test_methods[] = { {"test_lock_benchmark", test_lock_benchmark, METH_NOARGS}, {"test_lock_once", test_lock_once, METH_NOARGS}, {"test_lock_rwlock", test_lock_rwlock, METH_NOARGS}, + {"test_lock_recursive", test_lock_recursive, METH_NOARGS}, {NULL, NULL} /* sentinel */ }; diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 386e942..5f943d4 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -16,7 +16,6 @@ #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_ceval.h" // _PyEval_ReInitThreads() #include "pycore_fileutils.h" // _Py_closerange() -#include "pycore_import.h" // _PyImport_ReInitLock() #include "pycore_initconfig.h" // _PyStatus_EXCEPTION() #include "pycore_long.h" // _PyLong_IsNegative() #include "pycore_moduleobject.h" // _PyModule_GetState() @@ -627,10 +626,7 @@ PyOS_AfterFork_Parent(void) _PyEval_StartTheWorldAll(&_PyRuntime); PyInterpreterState *interp = _PyInterpreterState_GET(); - if (_PyImport_ReleaseLock(interp) <= 0) { - Py_FatalError("failed releasing import lock after fork"); - } - + _PyImport_ReleaseLock(interp); run_at_forkers(interp->after_forkers_parent, 0); } @@ -675,10 +671,7 @@ PyOS_AfterFork_Child(void) _PyEval_StartTheWorldAll(&_PyRuntime); _PyThreadState_DeleteList(list); - status = _PyImport_ReInitLock(tstate->interp); - if (_PyStatus_EXCEPTION(status)) { - goto fatal_error; - } + _PyImport_ReleaseLock(tstate->interp); _PySignal_AfterFork(); |