8000 [3.12] gh-105699: Use a Thread-Local Variable for PKGCONTEXT (gh-1057… · python/cpython@bc997b3 · GitHub
[go: up one dir, main page]

Skip to content

Commit bc997b3

Browse files
[3.12] gh-105699: Use a Thread-Local Variable for PKGCONTEXT (gh-105740) (gh-105765)
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 b87d288) Co-authored-by: Eric Snow <ericsnowcurrently@gmail.com>
1 parent 26bc2cc commit bc997b3

File tree

4 files changed

+24
-1
lines changed

4 files changed

+24
-1
lines changed

Python/import.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,28 +703,43 @@ _PyImport_ClearModulesByIndex(PyInterpreterState *interp)
703703
_PyRuntime.imports.pkgcontext, and PyModule_Create*() will
704704
substitute this (if the name actually matches).
705705
*/
706+
707+
#ifdef HAVE_THREAD_LOCAL
708+
_Py_thread_local const char *pkgcontext = NULL;
709+
# undef PKGCONTEXT
710+
# define PKGCONTEXT pkgcontext
711+
#endif
712+
706713
const char *
707714
_PyImport_ResolveNameWithPackageContext(const char *name)
708715
{
716+
#ifndef HAVE_THREAD_LOCAL
709717
PyThread_acquire_lock(EXTENSIONS.mutex, WAIT_LOCK);
718+
#endif
710719
if (PKGCONTEXT != NULL) {
711720
const char *p = strrchr(PKGCONTEXT, '.');
712721
if (p != NULL && strcmp(name, p+1) == 0) {
713722
name = PKGCONTEXT;
714723
PKGCONTEXT = NULL;
715724
}
716725
}
726+
#ifndef HAVE_THREAD_LOCAL
717727
PyThread_release_lock(EXTENSIONS.mutex);
728+
#endif
718729
return name;
719730
}
720731

721732
const char *
722733
_PyImport_SwapPackageContext(const char *newcontext)
723734
{
735+
#ifndef HAVE_THREAD_LOCAL
724736
PyThread_acquire_lock(EXTENSIONS.mutex, WAIT_LOCK);
737+
#endif
725738
const char *oldcontext = PKGCONTEXT;
726739
PKGCONTEXT = newcontext;
740+
#ifndef HAVE_THREAD_LOCAL
727741
PyThread_release_lock(EXTENSIONS.mutex);
742+
#endif
728743
return oldcontext;
729744
}
730745

Tools/c-analyzer/c_parser/parser/_regexes.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ def _ind(text, level=1, edges='both'):
5858
extern |
5959
register |
6060
static |
61+
_Thread_local |
6162
typedef |
6263
6364
const |
@@ -137,7 +138,7 @@ def _ind(text, level=1, edges='both'):
137138
#######################################
138139
# variable declarations
139140

140-
_STORAGE = 'auto register static extern'.split()
141+
_STORAGE = 'auto register static extern _Thread_local'.split()
141142
STORAGE_CLASS = rf'(?: \b (?: {" | ".join(_STORAGE)} ) \b )'
142143
TYPE_QUALIFIER = r'(?: \b (?: const | volatile ) \b )'
143144
PTR_QUALIFIER = rf'(?: [*] (?: \s* {TYPE_QUALIFIER} )? )'

Tools/c-analyzer/c_parser/preprocessor/gcc.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ def _strip_directives(line, partial=0):
219219
line = line[m.end():]
220220

221221
line = re.sub(r'__extension__', '', line)
222+
line = re.sub(r'__thread\b', '_Thread_local', line)
222223

223224
while (m := COMPILER_DIRECTIVE_RE.match(line)):
224225
before, _, _, closed = m.groups()

Tools/c-analyzer/cpython/ignored.tsv

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,12 @@ Modules/_xxinterpchannelsmodule.c - _globals -
168168

169169
Python/pyfpe.c - PyFPE_counter -
170170

171+
##-----------------------
172+
## thread-local variables
173+
174+
Python/import.c - pkgcontext -
175+
Python/pystate.c - _Py_tss_tstate -
176+
171177
##-----------------------
172178
## should be const
173179
# XXX Make them const.

0 commit comments

Comments
 (0)
0