aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python/import.c
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2023-06-13 18:58:23 -0600
committerGitHub <noreply@github.com>2023-06-13 18:58:23 -0600
commitb87d2882754a7c273e2695c33384383eba380d7d (patch)
tree55718e32fdacacf3dc3be2c8e6d00d02b9df193f /Python/import.c
parentfcf0647cf2a78de2c2b603af2709d58c8567df67 (diff)
downloadcpython-b87d2882754a7c273e2695c33384383eba380d7d.tar.gz
cpython-b87d2882754a7c273e2695c33384383eba380d7d.zip
gh-105699: Use a Thread-Local Variable for PKGCONTEXT (gh-105740)
This fixes a race during import. The existing _PyRuntimeState.imports.pkgcontext is shared between interpreters, and occasionally this would cause a crash when multiple interpreters were importing extensions modules at the same time. To solve this we add a thread-local variable for the value. We also leave the existing state (and infrequent race) in place for platforms that do not support thread-local variables.
Diffstat (limited to 'Python/import.c')
-rw-r--r--Python/import.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/Python/import.c b/Python/import.c
index 71cce8e4f62..779af55347a 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -703,10 +703,19 @@ _PyImport_ClearModulesByIndex(PyInterpreterState *interp)
_PyRuntime.imports.pkgcontext, and PyModule_Create*() will
substitute this (if the name actually matches).
*/
+
+#ifdef HAVE_THREAD_LOCAL
+_Py_thread_local const char *pkgcontext = NULL;
+# undef PKGCONTEXT
+# define PKGCONTEXT pkgcontext
+#endif
+
const char *
_PyImport_ResolveNameWithPackageContext(const char *name)
{
+#ifndef HAVE_THREAD_LOCAL
PyThread_acquire_lock(EXTENSIONS.mutex, WAIT_LOCK);
+#endif
if (PKGCONTEXT != NULL) {
const char *p = strrchr(PKGCONTEXT, '.');
if (p != NULL && strcmp(name, p+1) == 0) {
@@ -714,17 +723,23 @@ _PyImport_ResolveNameWithPackageContext(const char *name)
PKGCONTEXT = NULL;
}
}
+#ifndef HAVE_THREAD_LOCAL
PyThread_release_lock(EXTENSIONS.mutex);
+#endif
return name;
}
const char *
_PyImport_SwapPackageContext(const char *newcontext)
{
+#ifndef HAVE_THREAD_LOCAL
PyThread_acquire_lock(EXTENSIONS.mutex, WAIT_LOCK);
+#endif
const char *oldcontext = PKGCONTEXT;
PKGCONTEXT = newcontext;
+#ifndef HAVE_THREAD_LOCAL
PyThread_release_lock(EXTENSIONS.mutex);
+#endif
return oldcontext;
}