@@ -1410,10 +1410,12 @@ static int CPyImport_SetModuleSpec(PyObject *modobj, PyObject *module_name,
14101410PyObject * CPyImport_ImportNative (PyObject * module_name ,
14111411 PyObject * (* init_only_fn )(void ),
14121412 int (* exec_fn )(PyObject * ),
1413+ CPyModule * * module_static ,
14131414 PyObject * shared_lib_file , PyObject * ext_suffix ,
14141415 Py_ssize_t is_package ) {
14151416 PyObject * parent_module = NULL ;
14161417 PyObject * child_name = NULL ;
1418+ PyObject * exc_type , * exc_val , * exc_tb ;
14171419 Py_ssize_t name_len = PyUnicode_GetLength (module_name );
14181420 if (name_len < 0 ) {
14191421 return NULL ;
@@ -1449,27 +1451,45 @@ PyObject *CPyImport_ImportNative(PyObject *module_name,
14491451 return NULL ;
14501452 }
14511453
1452- PyObject * modobj = init_only_fn ();
1453- if (modobj == NULL ) {
1454+ PyObject * existing = PyDict_GetItemWithError (module_dict , module_name );
1455+ if (existing != NULL ) {
1456+ if (* module_static != NULL ) {
1457+ if (existing == (PyObject * )* module_static ) {
1458+ Py_INCREF (existing );
1459+ Py_XDECREF (parent_module );
1460+ Py_XDECREF (child_name );
1461+ return existing ;
1462+ }
1463+ PyErr_Format (PyExc_ImportError ,
1464+ "native module '%U' in sys.modules was replaced after initialization" ,
1465+ module_name );
1466+ Py_XDECREF (parent_module );
1467+ Py_XDECREF (child_name );
1468+ return NULL ;
1469+ }
1470+ }
1471+ if (PyErr_Occurred ()) {
14541472 Py_XDECREF (parent_module );
14551473 Py_XDECREF (child_name );
14561474 return NULL ;
14571475 }
14581476
1459- // Check if the module was already imported (e.g. via CPyInit_* from the
1460- // standard import machinery, or by a previous CPyImport_ImportNative call).
1461- int already_imported = PyDict_Contains (module_dict , module_name );
1462- if (already_imported < 0 ) {
1477+ PyObject * modobj = init_only_fn ();
1478+ if (modobj == NULL ) {
14631479 Py_XDECREF (parent_module );
14641480 Py_XDECREF (child_name );
1465- Py_DECREF (modobj );
14661481 return NULL ;
14671482 }
14681483
1469- if (!already_imported ) {
1470- if (PyObject_SetItem (module_dict , module_name , modobj ) < 0 ) {
1471- goto fail ;
1472- }
1484+ if (PyObject_SetItem (module_dict , module_name , modobj ) < 0 ) {
1485+ goto fail ;
1486+ }
1487+
1488+ if (* module_static != (CPyModule * )modobj ) {
1489+ PyErr_Format (PyExc_ImportError ,
1490+ "native module '%U' was initialized inconsistently" ,
1491+ module_name );
1492+ goto fail ;
14731493 }
14741494
14751495 // Set __package__ before executing the module body so it is available
@@ -1512,15 +1532,6 @@ PyObject *CPyImport_ImportNative(PyObject *module_name,
15121532 goto fail ;
15131533 }
15141534
1515- // If the module was already imported, skip executing the module body
1516- // (it was already executed). This handles circular imports and modules
1517- // first imported via the standard Python import machinery (CPyInit_*).
1518- if (already_imported ) {
1519- Py_XDECREF (parent_module );
1520- Py_XDECREF (child_name );
1521- return modobj ;
1522- }
1523-
15241535 // Now execute the module body, with __file__ and __package__ already set.
15251536 if (exec_fn (modobj ) != 0 ) {
15261537 goto fail ;
@@ -1537,15 +1548,12 @@ PyObject *CPyImport_ImportNative(PyObject *module_name,
15371548 return modobj ;
15381549
15391550fail :
1540- // Clean up on failure: if we added the module to sys.modules, remove it
1541- // so that a subsequent import attempt will retry initialization.
1542- if (!already_imported ) {
1543- PyObject * exc_type , * exc_val , * exc_tb ;
1544- PyErr_Fetch (& exc_type , & exc_val , & exc_tb );
1545- PyObject_DelItem (module_dict , module_name );
1546- PyErr_Clear ();
1547- PyErr_Restore (exc_type , exc_val , exc_tb );
1548- }
1551+ // Clean up on failure so that a subsequent import attempt will retry
1552+ // initialization.
1553+ PyErr_Fetch (& exc_type , & exc_val , & exc_tb );
1554+ PyObject_DelItem (module_dict , module_name );
1555+ PyErr_Clear ();
1556+ PyErr_Restore (exc_type , exc_val , exc_tb );
15491557 Py_XDECREF (parent_module );
15501558 Py_XDECREF (child_name );
15511559 Py_DECREF (modobj );
0 commit comments