summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2024-06-06 18:03:01 (GMT)
committerGitHub <noreply@github.com>2024-06-06 18:03:01 (GMT)
commit517733ce3cd7937dc527f1f191582c21cfb9b685 (patch)
tree64e0f07217be36c2991f65c8d9cd6c02114d5c68 /Modules
parent015ddfeca5e39a3796ee144d07accb1d5c7e7522 (diff)
downloadcpython-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.c25
-rw-r--r--Modules/posixmodule.c11
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();