Skip to content

Commit c3b4807

Browse files
committed
Fix bug in specialization and make reification atomic
1 parent cdec6a6 commit c3b4807

File tree

2 files changed

+17
-3
lines changed

2 files changed

+17
-3
lines changed

Python/import.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3712,20 +3712,25 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import)
37123712
assert(PyLazyImport_CheckExact(lazy_import));
37133713

37143714
PyLazyImportObject *lz = (PyLazyImportObject *)lazy_import;
3715+
PyInterpreterState *interp = tstate->interp;
3716+
3717+
// Acquire the global import lock to serialize reification
3718+
_PyImport_AcquireLock(interp);
37153719

37163720
// Check if we are already importing this module, if so, then we want to return an error
37173721
// that indicates we've hit a cycle which will indicate the value isn't yet available.
3718-
PyInterpreterState *interp = tstate->interp;
37193722
PyObject *importing = interp->imports.lazy_importing_modules;
37203723
if (importing == NULL) {
37213724
importing = interp->imports.lazy_importing_modules = PySet_New(NULL);
37223725
if (importing == NULL) {
3726+
_PyImport_ReleaseLock(interp);
37233727
return NULL;
37243728
}
37253729
}
37263730

37273731
int is_loading = PySet_Contains(importing, lazy_import);
37283732
if (is_loading < 0) {
3733+
_PyImport_ReleaseLock(interp);
37293734
return NULL;
37303735
} else if (is_loading == 1) {
37313736
PyObject *name = _PyLazyImport_GetName(lazy_import);
@@ -3735,8 +3740,10 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import)
37353740
PyErr_SetImportErrorSubclass(PyExc_ImportCycleError, errmsg, lz->lz_from, NULL);
37363741
Py_XDECREF(errmsg);
37373742
Py_XDECREF(name);
3743+
_PyImport_ReleaseLock(interp);
37383744
return NULL;
37393745
} else if (PySet_Add(importing, lazy_import) < 0) {
3746+
_PyImport_ReleaseLock(interp);
37403747
goto error;
37413748
}
37423749

@@ -3889,6 +3896,9 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import)
38893896
obj = NULL;
38903897
}
38913898

3899+
// Release the global import lock
3900+
_PyImport_ReleaseLock(interp);
3901+
38923902
Py_XDECREF(fromlist);
38933903
Py_XDECREF(import_func);
38943904
return obj;

Python/specialize.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1708,10 +1708,14 @@ specialize_load_global_lock_held(
17081708
goto fail;
17091709
}
17101710
PyObject *value = NULL;
1711-
if (PyDict_GetItemRef(globals, name, &value) < 0 ||
1712-
(value != NULL && PyLazyImport_CheckExact(value))) {
1711+
if (PyDict_GetItemRef(globals, name, &value) < 0) {
1712+
SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_EXPECTED_ERROR);
1713+
goto fail;
1714+
}
1715+
if (value != NULL && PyLazyImport_CheckExact(value)) {
17131716
SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_ATTR_MODULE_LAZY_VALUE);
17141717
Py_DECREF(value);
1718+
goto fail;
17151719
}
17161720
Py_XDECREF(value);
17171721
Py_ssize_t index = _PyDictKeys_StringLookup(globals_keys, name);

0 commit comments

Comments
 (0)