]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] gh-105699: Use a Thread-Local Variable for PKGCONTEXT (gh-105740) (gh-105765)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Wed, 14 Jun 2023 01:34:26 +0000 (18:34 -0700)
committerGitHub <noreply@github.com>
Wed, 14 Jun 2023 01:34:26 +0000 (01:34 +0000)
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.
(cherry picked from commit b87d2882754a7c273e2695c33384383eba380d7d)

Co-authored-by: Eric Snow <ericsnowcurrently@gmail.com>
Python/import.c
Tools/c-analyzer/c_parser/parser/_regexes.py
Tools/c-analyzer/c_parser/preprocessor/gcc.py
Tools/c-analyzer/cpython/ignored.tsv

index 9e1857d5f3e4e6c84f8b3096cddca3aefdf82e15..24723d64bd0c2a907e5cef9866d788ae45023423 100644 (file)
@@ -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;
 }
 
index b7f22b186f496567178b1f307dccab9e85048d76..5695daff67d6bd356aec259b6e18f9f18594f619 100644 (file)
@@ -58,6 +58,7 @@ _KEYWORD = textwrap.dedent(r'''
             extern |
             register |
             static |
+            _Thread_local |
             typedef |
 
             const |
@@ -137,7 +138,7 @@ COMPOUND_TYPE_KIND = r'(?: \b (?: struct | union | enum ) \b )'
 #######################################
 # variable declarations
 
-_STORAGE = 'auto register static extern'.split()
+_STORAGE = 'auto register static extern _Thread_local'.split()
 STORAGE_CLASS = rf'(?: \b (?: {" | ".join(_STORAGE)} ) \b )'
 TYPE_QUALIFIER = r'(?: \b (?: const | volatile ) \b )'
 PTR_QUALIFIER = rf'(?: [*] (?: \s* {TYPE_QUALIFIER} )? )'
index c680f351f224163b0b8be8cbe9d4ee30f711efc6..147615707a3cb83bedce643499d158174a4b7842 100644 (file)
@@ -219,6 +219,7 @@ def _strip_directives(line, partial=0):
         line = line[m.end():]
 
     line = re.sub(r'__extension__', '', line)
+    line = re.sub(r'__thread\b', '_Thread_local', line)
 
     while (m := COMPILER_DIRECTIVE_RE.match(line)):
         before, _, _, closed = m.groups()
index b6745b6aeb0b6139c84e1d3db532821e12b71ab2..afc28e551813b4b1cbbc7dac366a12abb33f10bd 100644 (file)
@@ -168,6 +168,12 @@ Modules/_xxinterpchannelsmodule.c  -       _globals        -
 
 Python/pyfpe.c -       PyFPE_counter   -
 
+##-----------------------
+## thread-local variables
+
+Python/import.c        -       pkgcontext      -
+Python/pystate.c       -       _Py_tss_tstate  -
+
 ##-----------------------
 ## should be const
 # XXX Make them const.