mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
Merge remote-tracking branch 'upstream/main' into lazy
This commit is contained in:
commit
db151a5192
869 changed files with 45727 additions and 16994 deletions
284
Python/import.c
284
Python/import.c
|
|
@ -3,6 +3,7 @@
|
|||
#include "Python.h"
|
||||
#include "pycore_audit.h" // _PySys_Audit()
|
||||
#include "pycore_ceval.h"
|
||||
#include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION()
|
||||
#include "pycore_hashtable.h" // _Py_hashtable_new_full()
|
||||
#include "pycore_import.h" // _PyImport_BootstrapImp()
|
||||
#include "pycore_initconfig.h" // _PyStatus_OK()
|
||||
|
|
@ -324,13 +325,8 @@ PyImport_GetModule(PyObject *name)
|
|||
if not, create a new one and insert it in the modules dictionary. */
|
||||
|
||||
static PyObject *
|
||||
import_add_module(PyThreadState *tstate, PyObject *name)
|
||||
import_add_module_lock_held(PyObject *modules, PyObject *name)
|
||||
{
|
||||
PyObject *modules = get_modules_dict(tstate, false);
|
||||
if (modules == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *m;
|
||||
if (PyMapping_GetOptionalItem(modules, name, &m) < 0) {
|
||||
return NULL;
|
||||
|
|
@ -350,6 +346,21 @@ import_add_module(PyThreadState *tstate, PyObject *name)
|
|||
return m;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
import_add_module(PyThreadState *tstate, PyObject *name)
|
||||
{
|
||||
PyObject *modules = get_modules_dict(tstate, false);
|
||||
if (modules == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *m;
|
||||
Py_BEGIN_CRITICAL_SECTION(modules);
|
||||
m = import_add_module_lock_held(modules, name);
|
||||
Py_END_CRITICAL_SECTION();
|
||||
return m;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PyImport_AddModuleRef(const char *name)
|
||||
{
|
||||
|
|
@ -687,8 +698,8 @@ _PyImport_ClearModulesByIndex(PyInterpreterState *interp)
|
|||
|
||||
(6). first time (not found in _PyRuntime.imports.extensions):
|
||||
A. _imp_create_dynamic_impl() -> import_find_extension()
|
||||
B. _imp_create_dynamic_impl() -> _PyImport_GetModInitFunc()
|
||||
C. _PyImport_GetModInitFunc(): load <module init func>
|
||||
B. _imp_create_dynamic_impl() -> _PyImport_GetModuleExportHooks()
|
||||
C. _PyImport_GetModuleExportHooks(): load <module init func>
|
||||
D. _imp_create_dynamic_impl() -> import_run_extension()
|
||||
E. import_run_extension() -> _PyImport_RunModInitFunc()
|
||||
F. _PyImport_RunModInitFunc(): call <module init func>
|
||||
|
|
@ -758,16 +769,19 @@ _PyImport_ClearModulesByIndex(PyInterpreterState *interp)
|
|||
A. noop
|
||||
|
||||
|
||||
...for multi-phase init modules:
|
||||
...for multi-phase init modules from PyModInit_* (PyModuleDef):
|
||||
|
||||
(6). every time:
|
||||
A. _imp_create_dynamic_impl() -> import_find_extension() (not found)
|
||||
B. _imp_create_dynamic_impl() -> _PyImport_GetModInitFunc()
|
||||
C. _PyImport_GetModInitFunc(): load <module init func>
|
||||
B. _imp_create_dynamic_impl() -> _PyImport_GetModuleExportHooks()
|
||||
C. _PyImport_GetModuleExportHooks(): load <module init func>
|
||||
D. _imp_create_dynamic_impl() -> import_run_extension()
|
||||
E. import_run_extension() -> _PyImport_RunModInitFunc()
|
||||
F. _PyImport_RunModInitFunc(): call <module init func>
|
||||
G. import_run_extension() -> PyModule_FromDefAndSpec()
|
||||
|
||||
PyModule_FromDefAndSpec():
|
||||
|
||||
H. PyModule_FromDefAndSpec(): gather/check moduledef slots
|
||||
I. if there's a Py_mod_create slot:
|
||||
1. PyModule_FromDefAndSpec(): call its function
|
||||
|
|
@ -780,10 +794,29 @@ _PyImport_ClearModulesByIndex(PyInterpreterState *interp)
|
|||
(10). every time:
|
||||
A. _imp_exec_dynamic_impl() -> exec_builtin_or_dynamic()
|
||||
B. if mod->md_state == NULL (including if m_size == 0):
|
||||
1. exec_builtin_or_dynamic() -> PyModule_ExecDef()
|
||||
2. PyModule_ExecDef(): allocate mod->md_state
|
||||
1. exec_builtin_or_dynamic() -> PyModule_Exec()
|
||||
2. PyModule_Exec(): allocate mod->md_state
|
||||
3. if there's a Py_mod_exec slot:
|
||||
1. PyModule_ExecDef(): call its function
|
||||
1. PyModule_Exec(): call its function
|
||||
|
||||
|
||||
...for multi-phase init modules from PyModExport_* (slots array):
|
||||
|
||||
(6). every time:
|
||||
|
||||
A. _imp_create_dynamic_impl() -> import_find_extension() (not found)
|
||||
B. _imp_create_dynamic_impl() -> _PyImport_GetModuleExportHooks()
|
||||
C. _PyImport_GetModuleExportHooks(): load <module export func>
|
||||
D. _imp_create_dynamic_impl() -> import_run_modexport()
|
||||
E. import_run_modexport(): call <module init func>
|
||||
F. import_run_modexport() -> PyModule_FromSlotsAndSpec()
|
||||
G. PyModule_FromSlotsAndSpec(): create temporary PyModuleDef-like
|
||||
H. PyModule_FromSlotsAndSpec() -> PyModule_FromDefAndSpec()
|
||||
|
||||
(PyModule_FromDefAndSpec behaves as for PyModInit_*, above)
|
||||
|
||||
(10). every time: as for PyModInit_*, above
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -797,7 +830,7 @@ _PyImport_ClearModulesByIndex(PyInterpreterState *interp)
|
|||
substitute this (if the name actually matches).
|
||||
*/
|
||||
|
||||
_Py_thread_local const char *pkgcontext = NULL;
|
||||
static _Py_thread_local const char *pkgcontext = NULL;
|
||||
# undef PKGCONTEXT
|
||||
# define PKGCONTEXT pkgcontext
|
||||
|
||||
|
|
@ -840,25 +873,19 @@ _PyImport_SetDLOpenFlags(PyInterpreterState *interp, int new_val)
|
|||
/* Common implementation for _imp.exec_dynamic and _imp.exec_builtin */
|
||||
static int
|
||||
exec_builtin_or_dynamic(PyObject *mod) {
|
||||
PyModuleDef *def;
|
||||
void *state;
|
||||
|
||||
if (!PyModule_Check(mod)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
def = PyModule_GetDef(mod);
|
||||
if (def == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
state = PyModule_GetState(mod);
|
||||
if (state) {
|
||||
/* Already initialized; skip reload */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return PyModule_ExecDef(mod, def);
|
||||
return PyModule_Exec(mod);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1016,9 +1043,10 @@ struct extensions_cache_value {
|
|||
_Py_ext_module_origin origin;
|
||||
|
||||
#ifdef Py_GIL_DISABLED
|
||||
/* The module's md_gil slot, for legacy modules that are reinitialized from
|
||||
m_dict rather than calling their initialization function again. */
|
||||
void *md_gil;
|
||||
/* The module's md_requires_gil member, for legacy modules that are
|
||||
* reinitialized from m_dict rather than calling their initialization
|
||||
* function again. */
|
||||
bool md_requires_gil;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
@ -1349,7 +1377,7 @@ static struct extensions_cache_value *
|
|||
_extensions_cache_set(PyObject *path, PyObject *name,
|
||||
PyModuleDef *def, PyModInitFunction m_init,
|
||||
Py_ssize_t m_index, PyObject *m_dict,
|
||||
_Py_ext_module_origin origin, void *md_gil)
|
||||
_Py_ext_module_origin origin, bool requires_gil)
|
||||
{
|
||||
struct extensions_cache_value *value = NULL;
|
||||
void *key = NULL;
|
||||
|
|
@ -1404,11 +1432,11 @@ _extensions_cache_set(PyObject *path, PyObject *name,
|
|||
/* m_dict is set by set_cached_m_dict(). */
|
||||
.origin=origin,
|
||||
#ifdef Py_GIL_DISABLED
|
||||
.md_gil=md_gil,
|
||||
.md_requires_gil=requires_gil,
|
||||
#endif
|
||||
};
|
||||
#ifndef Py_GIL_DISABLED
|
||||
(void)md_gil;
|
||||
(void)requires_gil;
|
||||
#endif
|
||||
if (init_cached_m_dict(newvalue, m_dict) < 0) {
|
||||
goto finally;
|
||||
|
|
@ -1546,26 +1574,13 @@ _PyImport_CheckGILForModule(PyObject* module, PyObject *module_name)
|
|||
}
|
||||
|
||||
if (!PyModule_Check(module) ||
|
||||
((PyModuleObject *)module)->md_gil == Py_MOD_GIL_USED) {
|
||||
if (_PyEval_EnableGILPermanent(tstate)) {
|
||||
int warn_result = PyErr_WarnFormat(
|
||||
PyExc_RuntimeWarning,
|
||||
1,
|
||||
"The global interpreter lock (GIL) has been enabled to load "
|
||||
"module '%U', which has not declared that it can run safely "
|
||||
"without the GIL. To override this behavior and keep the GIL "
|
||||
"disabled (at your own risk), run with PYTHON_GIL=0 or -Xgil=0.",
|
||||
module_name
|
||||
);
|
||||
if (warn_result < 0) {
|
||||
return warn_result;
|
||||
}
|
||||
((PyModuleObject *)module)->md_requires_gil)
|
||||
{
|
||||
if (PyModule_Check(module)) {
|
||||
assert(((PyModuleObject *)module)->md_token_is_def);
|
||||
}
|
||||
|
||||
const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
|
||||
if (config->enable_gil == _PyConfig_GIL_DEFAULT && config->verbose) {
|
||||
PySys_FormatStderr("# loading module '%U', which requires the GIL\n",
|
||||
module_name);
|
||||
if (_PyImport_EnableGILAndWarn(tstate, module_name) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -1574,6 +1589,28 @@ _PyImport_CheckGILForModule(PyObject* module, PyObject *module_name)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_PyImport_EnableGILAndWarn(PyThreadState *tstate, PyObject *module_name)
|
||||
{
|
||||
if (_PyEval_EnableGILPermanent(tstate)) {
|
||||
return PyErr_WarnFormat(
|
||||
PyExc_RuntimeWarning,
|
||||
1,
|
||||
"The global interpreter lock (GIL) has been enabled to load "
|
||||
"module '%U', which has not declared that it can run safely "
|
||||
"without the GIL. To override this behavior and keep the GIL "
|
||||
"disabled (at your own risk), run with PYTHON_GIL=0 or -Xgil=0.",
|
||||
module_name
|
||||
);
|
||||
}
|
||||
const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
|
||||
if (config->enable_gil == _PyConfig_GIL_DEFAULT && config->verbose) {
|
||||
PySys_FormatStderr("# loading module '%U', which requires the GIL\n",
|
||||
module_name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static PyThreadState *
|
||||
|
|
@ -1724,7 +1761,7 @@ struct singlephase_global_update {
|
|||
Py_ssize_t m_index;
|
||||
PyObject *m_dict;
|
||||
_Py_ext_module_origin origin;
|
||||
void *md_gil;
|
||||
bool md_requires_gil;
|
||||
};
|
||||
|
||||
static struct extensions_cache_value *
|
||||
|
|
@ -1783,7 +1820,7 @@ update_global_state_for_extension(PyThreadState *tstate,
|
|||
#endif
|
||||
cached = _extensions_cache_set(
|
||||
path, name, def, m_init, singlephase->m_index, m_dict,
|
||||
singlephase->origin, singlephase->md_gil);
|
||||
singlephase->origin, singlephase->md_requires_gil);
|
||||
if (cached == NULL) {
|
||||
// XXX Ignore this error? Doing so would effectively
|
||||
// mark the module as not loadable.
|
||||
|
|
@ -1802,7 +1839,7 @@ finish_singlephase_extension(PyThreadState *tstate, PyObject *mod,
|
|||
PyObject *name, PyObject *modules)
|
||||
{
|
||||
assert(mod != NULL && PyModule_Check(mod));
|
||||
assert(cached->def == _PyModule_GetDef(mod));
|
||||
assert(cached->def == _PyModule_GetDefOrNull(mod));
|
||||
|
||||
Py_ssize_t index = _get_cached_module_index(cached);
|
||||
if (_modules_by_index_set(tstate->interp, index, mod) < 0) {
|
||||
|
|
@ -1872,7 +1909,7 @@ reload_singlephase_extension(PyThreadState *tstate,
|
|||
if (def->m_base.m_copy != NULL) {
|
||||
// For non-core modules, fetch the GIL slot that was stored by
|
||||
// import_run_extension().
|
||||
((PyModuleObject *)mod)->md_gil = cached->md_gil;
|
||||
((PyModuleObject *)mod)->md_requires_gil = cached->md_requires_gil;
|
||||
}
|
||||
#endif
|
||||
/* We can't set mod->md_def if it's missing,
|
||||
|
|
@ -1880,8 +1917,8 @@ reload_singlephase_extension(PyThreadState *tstate,
|
|||
* due to violating interpreter isolation.
|
||||
* See the note in set_cached_m_dict().
|
||||
* Until that is solved, we leave md_def set to NULL. */
|
||||
assert(_PyModule_GetDef(mod) == NULL
|
||||
|| _PyModule_GetDef(mod) == def);
|
||||
assert(_PyModule_GetDefOrNull(mod) == NULL
|
||||
|| _PyModule_GetDefOrNull(mod) == def);
|
||||
}
|
||||
else {
|
||||
assert(cached->m_dict == NULL);
|
||||
|
|
@ -1968,6 +2005,43 @@ import_find_extension(PyThreadState *tstate,
|
|||
return mod;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
import_run_modexport(PyThreadState *tstate, PyModExportFunction ex0,
|
||||
struct _Py_ext_module_loader_info *info,
|
||||
PyObject *spec)
|
||||
{
|
||||
/* This is like import_run_extension, but avoids interpreter switching
|
||||
* and code for for single-phase modules.
|
||||
*/
|
||||
PyModuleDef_Slot *slots = ex0();
|
||||
if (!slots) {
|
||||
if (!PyErr_Occurred()) {
|
||||
PyErr_Format(
|
||||
PyExc_SystemError,
|
||||
"slot export function for module %s failed without setting an exception",
|
||||
info->name);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Format(
|
||||
PyExc_SystemError,
|
||||
"slot export function for module %s raised unreported exception",
|
||||
info->name);
|
||||
}
|
||||
PyObject *result = PyModule_FromSlotsAndSpec(slots, spec);
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyModule_Check(result)) {
|
||||
PyModuleObject *mod = (PyModuleObject *)result;
|
||||
if (mod && !mod->md_token) {
|
||||
mod->md_token = slots;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
import_run_extension(PyThreadState *tstate, PyModInitFunction p0,
|
||||
struct _Py_ext_module_loader_info *info,
|
||||
|
|
@ -2090,7 +2164,7 @@ import_run_extension(PyThreadState *tstate, PyModInitFunction p0,
|
|||
.m_index=def->m_base.m_index,
|
||||
.origin=info->origin,
|
||||
#ifdef Py_GIL_DISABLED
|
||||
.md_gil=((PyModuleObject *)mod)->md_gil,
|
||||
.md_requires_gil=((PyModuleObject *)mod)->md_requires_gil,
|
||||
#endif
|
||||
};
|
||||
// gh-88216: Extensions and def->m_base.m_copy can be updated
|
||||
|
|
@ -2140,7 +2214,7 @@ import_run_extension(PyThreadState *tstate, PyModInitFunction p0,
|
|||
assert_multiphase_def(def);
|
||||
assert(mod == NULL);
|
||||
/* Note that we cheat a little by not repeating the calls
|
||||
* to _PyImport_GetModInitFunc() and _PyImport_RunModInitFunc(). */
|
||||
* to _PyImport_GetModuleExportHooks() and _PyImport_RunModInitFunc(). */
|
||||
mod = PyModule_FromDefAndSpec(def, spec);
|
||||
if (mod == NULL) {
|
||||
goto error;
|
||||
|
|
@ -2254,8 +2328,9 @@ _PyImport_FixupBuiltin(PyThreadState *tstate, PyObject *mod, const char *name,
|
|||
return -1;
|
||||
}
|
||||
|
||||
PyModuleDef *def = PyModule_GetDef(mod);
|
||||
PyModuleDef *def = _PyModule_GetDefOrNull(mod);
|
||||
if (def == NULL) {
|
||||
assert(!PyErr_Occurred());
|
||||
PyErr_BadInternalCall();
|
||||
goto finally;
|
||||
}
|
||||
|
|
@ -2284,7 +2359,7 @@ _PyImport_FixupBuiltin(PyThreadState *tstate, PyObject *mod, const char *name,
|
|||
.origin=_Py_ext_module_origin_CORE,
|
||||
#ifdef Py_GIL_DISABLED
|
||||
/* Unused when m_dict == NULL. */
|
||||
.md_gil=NULL,
|
||||
.md_requires_gil=false,
|
||||
#endif
|
||||
};
|
||||
cached = update_global_state_for_extension(
|
||||
|
|
@ -2323,8 +2398,23 @@ is_builtin(PyObject *name)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static PyModInitFunction
|
||||
lookup_inittab_initfunc(const struct _Py_ext_module_loader_info* info)
|
||||
{
|
||||
for (struct _inittab *p = INITTAB; p->name != NULL; p++) {
|
||||
if (_PyUnicode_EqualToASCIIString(info->name, p->name)) {
|
||||
return (PyModInitFunction)p->initfunc;
|
||||
}
|
||||
}
|
||||
// not found
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec)
|
||||
create_builtin(
|
||||
PyThreadState *tstate, PyObject *name,
|
||||
PyObject *spec,
|
||||
PyModInitFunction initfunc)
|
||||
{
|
||||
struct _Py_ext_module_loader_info info;
|
||||
if (_Py_ext_module_loader_info_init_for_builtin(&info, name) < 0) {
|
||||
|
|
@ -2337,8 +2427,8 @@ create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec)
|
|||
assert(!_PyErr_Occurred(tstate));
|
||||
assert(cached != NULL);
|
||||
/* The module might not have md_def set in certain reload cases. */
|
||||
assert(_PyModule_GetDef(mod) == NULL
|
||||
|| cached->def == _PyModule_GetDef(mod));
|
||||
assert(_PyModule_GetDefOrNull(mod) == NULL
|
||||
|| cached->def == _PyModule_GetDefOrNull(mod));
|
||||
assert_singlephase(cached);
|
||||
goto finally;
|
||||
}
|
||||
|
|
@ -2355,25 +2445,15 @@ create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec)
|
|||
_extensions_cache_delete(info.path, info.name);
|
||||
}
|
||||
|
||||
struct _inittab *found = NULL;
|
||||
for (struct _inittab *p = INITTAB; p->name != NULL; p++) {
|
||||
if (_PyUnicode_EqualToASCIIString(info.name, p->name)) {
|
||||
found = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found == NULL) {
|
||||
// not found
|
||||
mod = Py_NewRef(Py_None);
|
||||
goto finally;
|
||||
}
|
||||
|
||||
PyModInitFunction p0 = (PyModInitFunction)found->initfunc;
|
||||
PyModInitFunction p0 = initfunc;
|
||||
if (p0 == NULL) {
|
||||
/* Cannot re-init internal module ("sys" or "builtins") */
|
||||
assert(is_core_module(tstate->interp, info.name, info.path));
|
||||
mod = import_add_module(tstate, info.name);
|
||||
goto finally;
|
||||
p0 = lookup_inittab_initfunc(&info);
|
||||
if (p0 == NULL) {
|
||||
/* Cannot re-init internal module ("sys" or "builtins") */
|
||||
assert(is_core_module(tstate->interp, info.name, info.path));
|
||||
mod = import_add_module(tstate, info.name);
|
||||
goto finally;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef Py_GIL_DISABLED
|
||||
|
|
@ -2399,6 +2479,33 @@ create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec)
|
|||
return mod;
|
||||
}
|
||||
|
||||
PyObject*
|
||||
PyImport_CreateModuleFromInitfunc(
|
||||
PyObject *spec, PyObject *(*initfunc)(void))
|
||||
{
|
||||
if (initfunc == NULL) {
|
||||
PyErr_BadInternalCall();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
|
||||
PyObject *name = PyObject_GetAttr(spec, &_Py_ID(name));
|
||||
if (name == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!PyUnicode_Check(name)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"spec name must be string, not %T", name);
|
||||
Py_DECREF(name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *mod = create_builtin(tstate, name, spec, initfunc);
|
||||
Py_DECREF(name);
|
||||
return mod;
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
/* the builtin modules table */
|
||||
|
|
@ -3168,7 +3275,7 @@ bootstrap_imp(PyThreadState *tstate)
|
|||
}
|
||||
|
||||
// Create the _imp module from its definition.
|
||||
PyObject *mod = create_builtin(tstate, name, spec);
|
||||
PyObject *mod = create_builtin(tstate, name, spec, NULL);
|
||||
Py_CLEAR(name);
|
||||
Py_DECREF(spec);
|
||||
if (mod == NULL) {
|
||||
|
|
@ -4798,7 +4905,7 @@ _imp_create_builtin(PyObject *module, PyObject *spec)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
PyObject *mod = create_builtin(tstate, name, spec);
|
||||
PyObject *mod = create_builtin(tstate, name, spec, NULL);
|
||||
Py_DECREF(name);
|
||||
return mod;
|
||||
}
|
||||
|
|
@ -5138,8 +5245,8 @@ _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file)
|
|||
assert(!_PyErr_Occurred(tstate));
|
||||
assert(cached != NULL);
|
||||
/* The module might not have md_def set in certain reload cases. */
|
||||
assert(_PyModule_GetDef(mod) == NULL
|
||||
|| cached->def == _PyModule_GetDef(mod));
|
||||
assert(_PyModule_GetDefOrNull(mod) == NULL
|
||||
|| cached->def == _PyModule_GetDefOrNull(mod));
|
||||
assert_singlephase(cached);
|
||||
goto finally;
|
||||
}
|
||||
|
|
@ -5164,7 +5271,7 @@ _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file)
|
|||
}
|
||||
|
||||
/* We would move this (and the fclose() below) into
|
||||
* _PyImport_GetModInitFunc(), but it isn't clear if the intervening
|
||||
* _PyImport_GetModuleExportHooks(), but it isn't clear if the intervening
|
||||
* code relies on fp still being open. */
|
||||
FILE *fp;
|
||||
if (file != NULL) {
|
||||
|
|
@ -5177,7 +5284,15 @@ _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file)
|
|||
fp = NULL;
|
||||
}
|
||||
|
||||
PyModInitFunction p0 = _PyImport_GetModInitFunc(&info, fp);
|
||||
PyModInitFunction p0 = NULL;
|
||||
PyModExportFunction ex0 = NULL;
|
||||
_PyImport_GetModuleExportHooks(&info, fp, &p0, &ex0);
|
||||
if (ex0) {
|
||||
mod = import_run_modexport(tstate, ex0, &info, spec);
|
||||
// Modules created from slots handle GIL enablement (Py_mod_gil slot)
|
||||
// when they're created.
|
||||
goto cleanup;
|
||||
}
|
||||
if (p0 == NULL) {
|
||||
goto finally;
|
||||
}
|
||||
|
|
@ -5199,6 +5314,7 @@ _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file)
|
|||
}
|
||||
#endif
|
||||
|
||||
cleanup:
|
||||
// XXX Shouldn't this happen in the error cases too (i.e. in "finally")?
|
||||
if (fp) {
|
||||
fclose(fp);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue