@@ -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