Skip to content

Commit d862799

Browse files
pythongh-100227: Add a Granular Lock for _PyRuntime.imports.extensions.dict (pythongh-103460)
The lock is unnecessary as long as there's a GIL, but completely necessary with a per-interpreter GIL.
1 parent b934f97 commit d862799

File tree

3 files changed

+16
-4
lines changed

3 files changed

+16
-4
lines changed

Include/internal/pycore_import.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ struct _import_runtime_state {
1919
used exclusively for when the extensions dict is access/modified
2020
from an arbitrary thread. */
2121
PyThreadState main_tstate;
22+
/* A lock to guard the dict. */
23+
PyThread_type_lock mutex;
2224
/* A dict mapping (filename, name) to PyModuleDef for modules.
2325
Only legacy (single-phase init) extension modules are added
2426
and only if they support multiple initialization (m_size >- 0)

Python/import.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -413,8 +413,11 @@ remove_module(PyThreadState *tstate, PyObject *name)
413413
Py_ssize_t
414414
_PyImport_GetNextModuleIndex(void)
415415
{
416+
PyThread_acquire_lock(EXTENSIONS.mutex, WAIT_LOCK);
416417
LAST_MODULE_INDEX++;
417-
return LAST_MODULE_INDEX;
418+
Py_ssize_t index = LAST_MODULE_INDEX;
419+
PyThread_release_lock(EXTENSIONS.mutex);
420+
return index;
418421
}
419422

420423
static const char *
@@ -703,21 +706,25 @@ _PyImport_ClearModulesByIndex(PyInterpreterState *interp)
703706
const char *
704707
_PyImport_ResolveNameWithPackageContext(const char *name)
705708
{
709+
PyThread_acquire_lock(EXTENSIONS.mutex, WAIT_LOCK);
706710
if (PKGCONTEXT != NULL) {
707711
const char *p = strrchr(PKGCONTEXT, '.');
708712
if (p != NULL && strcmp(name, p+1) == 0) {
709713
name = PKGCONTEXT;
710714
PKGCONTEXT = NULL;
711715
}
712716
}
717+
PyThread_release_lock(EXTENSIONS.mutex);
713718
return name;
714719
}
715720

716721
const char *
717722
_PyImport_SwapPackageContext(const char *newcontext)
718723
{
724+
PyThread_acquire_lock(EXTENSIONS.mutex, WAIT_LOCK);
719725
const char *oldcontext = PKGCONTEXT;
720726
PKGCONTEXT = newcontext;
727+
PyThread_release_lock(EXTENSIONS.mutex);
721728
return oldcontext;
722729
}
723730

@@ -865,13 +872,13 @@ gets even messier.
865872
static inline void
866873
extensions_lock_acquire(void)
867874
{
868-
// XXX For now the GIL is sufficient.
875+
PyThread_acquire_lock(_PyRuntime.imports.extensions.mutex, WAIT_LOCK);
869876
}
870877

871878
static inline void
872879
extensions_lock_release(void)
873880
{
874-
// XXX For now the GIL is sufficient.
881+
PyThread_release_lock(_PyRuntime.imports.extensions.mutex);
875882
}
876883

877884
/* Magic for extension modules (built-in as well as dynamically

Python/pystate.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ _Py_COMP_DIAG_IGNORE_DEPR_DECLS
380380
static const _PyRuntimeState initial = _PyRuntimeState_INIT(_PyRuntime);
381381
_Py_COMP_DIAG_POP
382382

383-
#define NUMLOCKS 4
383+
#define NUMLOCKS 5
384384

385385
static int
386386
alloc_for_runtime(PyThread_type_lock locks[NUMLOCKS])
@@ -434,6 +434,7 @@ init_runtime(_PyRuntimeState *runtime,
434434
&runtime->xidregistry.mutex,
435435
&runtime->getargs.mutex,
436436
&runtime->unicode_state.ids.lock,
437+
&runtime->imports.extensions.mutex,
437438
};
438439
for (int i = 0; i < NUMLOCKS; i++) {
439440
assert(locks[i] != NULL);
@@ -518,6 +519,7 @@ _PyRuntimeState_Fini(_PyRuntimeState *runtime)
518519
&runtime->xidregistry.mutex,
519520
&runtime->getargs.mutex,
520521
&runtime->unicode_state.ids.lock,
522+
&runtime->imports.extensions.mutex,
521523
};
522524
for (int i = 0; i < NUMLOCKS; i++) {
523525
FREE_LOCK(*lockptrs[i]);
@@ -546,6 +548,7 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime)
546548
&runtime->xidregistry.mutex,
547549
&runtime->getargs.mutex,
548550
&runtime->unicode_state.ids.lock,
551+
&runtime->imports.extensions.mutex,
549552
};
550553
int reinit_err = 0;
551554
for (int i = 0; i < NUMLOCKS; i++) {

0 commit comments

Comments
 (0)