@@ -632,44 +632,45 @@ _PyImport_ClearModulesByIndex(PyInterpreterState *interp)
632632
633633 (6). first time (not found in _PyRuntime.imports.extensions):
634634 A. _imp_create_dynamic_impl() -> import_find_extension()
635- B. _imp_create_dynamic_impl() -> _PyImport_LoadDynamicModuleWithSpec()
636- C. _PyImport_LoadDynamicModuleWithSpec(): load <module init func>
637- D. _PyImport_LoadDynamicModuleWithSpec(): call <module init func>
638- E. <module init func> -> PyModule_Create() -> PyModule_Create2()
635+ B. _imp_create_dynamic_impl() -> _PyImport_GetModInitFunc()
636+ C. _PyImport_GetModInitFunc(): load <module init func>
637+ D. _imp_create_dynamic_impl() -> _PyImport_RunModInitFunc()
638+ E. _PyImport_RunModInitFunc(): call <module init func>
639+ F. <module init func> -> PyModule_Create() -> PyModule_Create2()
639640 -> PyModule_CreateInitialized()
640- F. PyModule_CreateInitialized() -> PyModule_New()
641- G. PyModule_CreateInitialized(): allocate mod->md_state
642- H. PyModule_CreateInitialized() -> PyModule_AddFunctions()
643- I. PyModule_CreateInitialized() -> PyModule_SetDocString()
644- J. PyModule_CreateInitialized(): set mod->md_def
645- K. <module init func>: initialize the module, etc.
646- L. _PyImport_LoadDynamicModuleWithSpec()
647- -> _PyImport_CheckSubinterpIncompatibleExtensionAllowed()
648- M. _PyImport_LoadDynamicModuleWithSpec(): set def->m_base.m_init
649- N. _PyImport_LoadDynamicModuleWithSpec() -> _PyImport_FixupExtensionObject()
650- O. _PyImport_FixupExtensionObject() -> update_global_state_for_extension()
651- P. update_global_state_for_extension():
652- copy __dict__ into def->m_base.m_copy
653- Q. update_global_state_for_extension():
654- add it to _PyRuntime.imports.extensions
655- R. _PyImport_FixupExtensionObject() -> finish_singlephase_extension()
656- S. finish_singlephase_extension():
657- add it to interp->imports.modules_by_index
658- T. finish_singlephase_extension(): add it to sys.modules
659- U. _imp_create_dynamic_impl(): set __file__
660-
661- Step (P) is skipped for core modules (sys/builtins).
641+ G. PyModule_CreateInitialized() -> PyModule_New()
642+ H. PyModule_CreateInitialized(): allocate mod->md_state
643+ I. PyModule_CreateInitialized() -> PyModule_AddFunctions()
644+ J. PyModule_CreateInitialized() -> PyModule_SetDocString()
645+ K. PyModule_CreateInitialized(): set mod->md_def
646+ L. <module init func>: initialize the module, etc.
647+ M. _PyImport_RunModInitFunc(): set def->m_base.m_init
648+ N. _imp_create_dynamic_impl()
649+ -> _PyImport_CheckSubinterpIncompatibleExtensionAllowed()
650+ O. _imp_create_dynamic_impl(): set __file__
651+ P. _imp_create_dynamic_impl() -> update_global_state_for_extension()
652+ Q. update_global_state_for_extension():
653+ copy __dict__ into def->m_base.m_copy
654+ R. update_global_state_for_extension():
655+ add it to _PyRuntime.imports.extensions
656+ S. _imp_create_dynamic_impl() -> finish_singlephase_extension()
657+ T. finish_singlephase_extension():
658+ add it to interp->imports.modules_by_index
659+ U. finish_singlephase_extension(): add it to sys.modules
660+
661+ Step (Q) is skipped for core modules (sys/builtins).
662662
663663 (6). subsequent times (found in _PyRuntime.imports.extensions):
664664 A. _imp_create_dynamic_impl() -> import_find_extension()
665- B. import_find_extension() -> import_add_module()
666- C. if name in sys.modules: use that module
667- D. else:
665+ B. import_find_extension()
666+ -> _PyImport_CheckSubinterpIncompatibleExtensionAllowed()
667+ C. import_find_extension() -> import_add_module()
668+ D. if name in sys.modules: use that module
669+ E. else:
668670 1. import_add_module() -> PyModule_NewObject()
669671 2. import_add_module(): set it on sys.modules
670- E. import_find_extension(): copy the "m_copy" dict into __dict__
671- F. _imp_create_dynamic_impl()
672- -> _PyImport_CheckSubinterpIncompatibleExtensionAllowed()
672+ F. import_find_extension(): copy the "m_copy" dict into __dict__
673+ G. import_find_extension(): add to modules_by_index
673674
674675 (10). (every time):
675676 A. noop
@@ -678,19 +679,22 @@ _PyImport_ClearModulesByIndex(PyInterpreterState *interp)
678679 ...for single-phase init modules, where m_size >= 0:
679680
680681 (6). not main interpreter and never loaded there - every time (not found in _PyRuntime.imports.extensions):
681- A-N . (same as for m_size == -1)
682- O-Q . (skipped)
683- R -U. (same as for m_size == -1)
682+ A-O . (same as for m_size == -1)
683+ P-R . (skipped)
684+ S -U. (same as for m_size == -1)
684685
685686 (6). main interpreter - first time (not found in _PyRuntime.imports.extensions):
686- A-O . (same as for m_size == -1)
687- P . (skipped)
688- Q -U. (same as for m_size == -1)
687+ A-Q . (same as for m_size == -1)
688+ R . (skipped)
689+ S -U. (same as for m_size == -1)
689690
690- (6). previously loaded in main interpreter (found in _PyRuntime.imports.extensions):
691+ (6). subsequent times (found in _PyRuntime.imports.extensions):
691692 A. _imp_create_dynamic_impl() -> import_find_extension()
692- B. import_find_extension(): call def->m_base.m_init
693- C. import_find_extension(): add the module to sys.modules
693+ B. import_find_extension()
694+ -> _PyImport_CheckSubinterpIncompatibleExtensionAllowed()
695+ C. import_find_extension(): call def->m_base.m_init (see above)
696+ D. import_find_extension(): add the module to sys.modules
697+ E. import_find_extension(): add to modules_by_index
694698
695699 (10). every time:
696700 A. noop
@@ -1270,7 +1274,7 @@ finish_singlephase_extension(PyThreadState *tstate,
12701274 PyObject *name, PyObject *modules)
12711275{
12721276 assert(mod != NULL && PyModule_Check(mod));
1273- assert(def == PyModule_GetDef (mod));
1277+ assert(def == _PyModule_GetDef (mod));
12741278
12751279 if (_modules_by_index_set(tstate->interp, def, mod) < 0) {
12761280 return -1;
@@ -1285,47 +1289,6 @@ finish_singlephase_extension(PyThreadState *tstate,
12851289 return 0;
12861290}
12871291
1288- int
1289- _PyImport_FixupExtensionObject(PyObject *mod, PyObject *name,
1290- PyObject *filename, PyObject *modules)
1291- {
1292- PyThreadState *tstate = _PyThreadState_GET();
1293-
1294- if (mod == NULL || !PyModule_Check(mod)) {
1295- PyErr_BadInternalCall();
1296- return -1;
1297- }
1298- PyModuleDef *def = PyModule_GetDef(mod);
1299- if (def == NULL) {
1300- PyErr_BadInternalCall();
1301- return -1;
1302- }
1303-
1304- /* Only single-phase init extension modules can reach here. */
1305- assert(is_singlephase(def));
1306- assert(!is_core_module(tstate->interp, name, filename));
1307- assert(!is_core_module(tstate->interp, name, name));
1308-
1309- struct singlephase_global_update singlephase = {0};
1310- // gh-88216: Extensions and def->m_base.m_copy can be updated
1311- // when the extension module doesn't support sub-interpreters.
1312- if (def->m_size == -1) {
1313- singlephase.m_dict = PyModule_GetDict(mod);
1314- assert(singlephase.m_dict != NULL);
1315- }
1316- if (update_global_state_for_extension(
1317- tstate, filename, name, def, &singlephase) < 0)
1318- {
1319- return -1;
1320- }
1321-
1322- if (finish_singlephase_extension(tstate, mod, def, name, modules) < 0) {
1323- return -1;
1324- }
1325-
1326- return 0;
1327- }
1328-
13291292
13301293static PyObject *
13311294import_find_extension(PyThreadState *tstate,
@@ -1514,7 +1477,12 @@ create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec)
15141477 }
15151478
15161479 PyObject *mod = import_find_extension(tstate, &info);
1517- if (mod || _PyErr_Occurred(tstate)) {
1480+ if (mod != NULL) {
1481+ assert(!_PyErr_Occurred(tstate));
1482+ assert(is_singlephase(_PyModule_GetDef(mod)));
1483+ goto finally;
1484+ }
1485+ else if (_PyErr_Occurred(tstate)) {
15181486 goto finally;
15191487 }
15201488
@@ -3900,31 +3868,35 @@ _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file)
39003868/*[clinic end generated code: output=83249b827a4fde77 input=c31b954f4cf4e09d]*/
39013869{
39023870 PyObject *mod = NULL;
3903- FILE *fp;
3871+ PyModuleDef *def = NULL;
3872+ PyThreadState *tstate = _PyThreadState_GET();
39043873
39053874 struct _Py_ext_module_loader_info info;
39063875 if (_Py_ext_module_loader_info_init_from_spec(&info, spec) < 0) {
39073876 return NULL;
39083877 }
39093878
3910- PyThreadState *tstate = _PyThreadState_GET();
39113879 mod = import_find_extension(tstate, &info);
3912- if (mod != NULL || _PyErr_Occurred(tstate)) {
3913- assert(mod == NULL || !_PyErr_Occurred(tstate));
3880+ if (mod != NULL) {
3881+ assert(!_PyErr_Occurred(tstate));
3882+ assert(is_singlephase(_PyModule_GetDef(mod)));
39143883 goto finally;
39153884 }
3885+ else if (_PyErr_Occurred(tstate)) {
3886+ goto finally;
3887+ }
3888+ /* Otherwise it must be multi-phase init or the first time it's loaded. */
39163889
39173890 if (PySys_Audit("import", "OOOOO", info.name, info.filename,
39183891 Py_None, Py_None, Py_None) < 0)
39193892 {
39203893 goto finally;
39213894 }
39223895
3923- /* Is multi-phase init or this is the first time being loaded. */
3924-
39253896 /* We would move this (and the fclose() below) into
39263897 * _PyImport_GetModInitFunc(), but it isn't clear if the intervening
39273898 * code relies on fp still being open. */
3899+ FILE *fp;
39283900 if (file != NULL) {
39293901 fp = _Py_fopen_obj(info.filename, "r");
39303902 if (fp == NULL) {
@@ -3935,7 +3907,70 @@ _imp_create_dynamic_impl(PyObject *module, PyObject *spec, PyObject *file)
39353907 fp = NULL;
39363908 }
39373909
3938- mod = _PyImport_LoadDynamicModuleWithSpec(&info, spec, fp);
3910+ PyModInitFunction p0 = _PyImport_GetModInitFunc(&info, fp);
3911+ if (p0 == NULL) {
3912+ goto finally;
3913+ }
3914+
3915+ struct _Py_ext_module_loader_result res;
3916+ if (_PyImport_RunModInitFunc(p0, &info, &res) < 0) {
3917+ assert(PyErr_Occurred());
3918+ goto finally;
3919+ }
3920+
3921+ mod = res.module;
3922+ res.module = NULL;
3923+ def = res.def;
3924+ assert(def != NULL);
3925+
3926+ if (mod == NULL) {
3927+ //assert(!is_singlephase(def));
3928+ mod = PyModule_FromDefAndSpec(def, spec);
3929+ if (mod == NULL) {
3930+ goto finally;
3931+ }
3932+ }
3933+ else {
3934+ assert(is_singlephase(def));
3935+ assert(!is_core_module(tstate->interp, info.name, info.filename));
3936+ assert(!is_core_module(tstate->interp, info.name, info.name));
3937+
3938+ const char *name_buf = PyBytes_AS_STRING(info.name_encoded);
3939+ if (_PyImport_CheckSubinterpIncompatibleExtensionAllowed(name_buf) < 0) {
3940+ Py_CLEAR(mod);
3941+ goto finally;
3942+ }
3943+
3944+ /* Remember pointer to module init function. */
3945+ res.def->m_base.m_init = p0;
3946+
3947+ /* Remember the filename as the __file__ attribute */
3948+ if (PyModule_AddObjectRef(mod, "__file__", info.filename) < 0) {
3949+ PyErr_Clear(); /* Not important enough to report */
3950+ }
3951+
3952+ struct singlephase_global_update singlephase = {0};
3953+ // gh-88216: Extensions and def->m_base.m_copy can be updated
3954+ // when the extension module doesn't support sub-interpreters.
3955+ if (def->m_size == -1) {
3956+ singlephase.m_dict = PyModule_GetDict(mod);
3957+ assert(singlephase.m_dict != NULL);
3958+ }
3959+ if (update_global_state_for_extension(
3960+ tstate, info.filename, info.name, def, &singlephase) < 0)
3961+ {
3962+ Py_CLEAR(mod);
3963+ goto finally;
3964+ }
3965+
3966+ PyObject *modules = get_modules_dict(tstate, true);
3967+ if (finish_singlephase_extension(
3968+ tstate, mod, def, info.name, modules) < 0)
3969+ {
3970+ Py_CLEAR(mod);
3971+ goto finally;
3972+ }
3973+ }
39393974
39403975 // XXX Shouldn't this happen in the error cases too.
39413976 if (fp) {
0 commit comments