summaryrefslogtreecommitdiffstats
path: root/Include
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 /Include
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 'Include')
-rw-r--r--Include/internal/pycore_import.h18
-rw-r--r--Include/internal/pycore_lock.h12
2 files changed, 14 insertions, 16 deletions
diff --git a/Include/internal/pycore_import.h b/Include/internal/pycore_import.h
index bd40707..3806e0d 100644
--- a/Include/internal/pycore_import.h
+++ b/Include/internal/pycore_import.h
@@ -20,7 +20,7 @@ PyAPI_FUNC(int) _PyImport_SetModule(PyObject *name, PyObject *module);
extern int _PyImport_SetModuleString(const char *name, PyObject* module);
extern void _PyImport_AcquireLock(PyInterpreterState *interp);
-extern int _PyImport_ReleaseLock(PyInterpreterState *interp);
+extern void _PyImport_ReleaseLock(PyInterpreterState *interp);
// This is used exclusively for the sys and builtins modules:
extern int _PyImport_FixupBuiltin(
@@ -94,11 +94,7 @@ struct _import_state {
#endif
PyObject *import_func;
/* The global import lock. */
- struct {
- PyThread_type_lock mutex;
- unsigned long thread;
- int level;
- } lock;
+ _PyRecursiveMutex lock;
/* diagnostic info in PyImport_ImportModuleLevelObject() */
struct {
int import_level;
@@ -123,11 +119,6 @@ struct _import_state {
#define IMPORTS_INIT \
{ \
DLOPENFLAGS_INIT \
- .lock = { \
- .mutex = NULL, \
- .thread = PYTHREAD_INVALID_THREAD_ID, \
- .level = 0, \
- }, \
.find_and_load = { \
.header = 1, \
}, \
@@ -180,11 +171,6 @@ extern void _PyImport_FiniCore(PyInterpreterState *interp);
extern void _PyImport_FiniExternal(PyInterpreterState *interp);
-#ifdef HAVE_FORK
-extern PyStatus _PyImport_ReInitLock(PyInterpreterState *interp);
-#endif
-
-
extern PyObject* _PyImport_GetBuiltinModuleNames(void);
struct _module_alias {
diff --git a/Include/internal/pycore_lock.h b/Include/internal/pycore_lock.h
index a5b28e4..d5853b2 100644
--- a/Include/internal/pycore_lock.h
+++ b/Include/internal/pycore_lock.h
@@ -219,6 +219,18 @@ _PyOnceFlag_CallOnce(_PyOnceFlag *flag, _Py_once_fn_t *fn, void *arg)
return _PyOnceFlag_CallOnceSlow(flag, fn, arg);
}
+// A recursive mutex. The mutex should zero-initialized.
+typedef struct {
+ PyMutex mutex;
+ unsigned long long thread; // i.e., PyThread_get_thread_ident_ex()
+ size_t level;
+} _PyRecursiveMutex;
+
+PyAPI_FUNC(int) _PyRecursiveMutex_IsLockedByCurrentThread(_PyRecursiveMutex *m);
+PyAPI_FUNC(void) _PyRecursiveMutex_Lock(_PyRecursiveMutex *m);
+PyAPI_FUNC(void) _PyRecursiveMutex_Unlock(_PyRecursiveMutex *m);
+
+
// A readers-writer (RW) lock. The lock supports multiple concurrent readers or
// a single writer. The lock is write-preferring: if a writer is waiting while
// the lock is read-locked then, new readers will be blocked. This avoids