mirror of
https://github.com/python/cpython.git
synced 2025-08-27 04:05:34 +00:00
gh-123880: Allow recursive import of single-phase-init modules (GH-123950)
Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Co-authored-by: Brett Cannon <brett@python.org>
This commit is contained in:
parent
3e36e5aef1
commit
aee219f455
6 changed files with 141 additions and 25 deletions
|
@ -815,6 +815,8 @@ static int clear_singlephase_extension(PyInterpreterState *interp,
|
|||
|
||||
// Currently, this is only used for testing.
|
||||
// (See _testinternalcapi.clear_extension().)
|
||||
// If adding another use, be careful about modules that import themselves
|
||||
// recursively (see gh-123880).
|
||||
int
|
||||
_PyImport_ClearExtension(PyObject *name, PyObject *filename)
|
||||
{
|
||||
|
@ -1322,12 +1324,16 @@ _extensions_cache_set(PyObject *path, PyObject *name,
|
|||
value = entry == NULL
|
||||
? NULL
|
||||
: (struct extensions_cache_value *)entry->value;
|
||||
/* We should never be updating an existing cache value. */
|
||||
assert(value == NULL);
|
||||
if (value != NULL) {
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"extension module %R is already cached", name);
|
||||
goto finally;
|
||||
/* gh-123880: If there's an existing cache value, it means a module is
|
||||
* being imported recursively from its PyInit_* or Py_mod_* function.
|
||||
* (That function presumably handles returning a partially
|
||||
* constructed module in such a case.)
|
||||
* We can reuse the existing cache value; it is owned by the cache.
|
||||
* (Entries get removed from it in exceptional circumstances,
|
||||
* after interpreter shutdown, and in runtime shutdown.)
|
||||
*/
|
||||
goto finally_oldvalue;
|
||||
}
|
||||
newvalue = alloc_extensions_cache_value();
|
||||
if (newvalue == NULL) {
|
||||
|
@ -1392,6 +1398,7 @@ finally:
|
|||
cleanup_old_cached_def(&olddefbase);
|
||||
}
|
||||
|
||||
finally_oldvalue:
|
||||
extensions_lock_release();
|
||||
if (key != NULL) {
|
||||
hashtable_destroy_str(key);
|
||||
|
@ -2128,6 +2135,7 @@ error:
|
|||
}
|
||||
|
||||
|
||||
// Used in _PyImport_ClearExtension; see notes there.
|
||||
static int
|
||||
clear_singlephase_extension(PyInterpreterState *interp,
|
||||
PyObject *name, PyObject *path)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue