@@ -1527,48 +1527,22 @@ _PyImport_CheckSubinterpIncompatibleExtensionAllowed(const char *name)
15271527}
15281528
15291529static PyThreadState *
1530- maybe_switch_to_main_interpreter (PyThreadState * tstate )
1530+ switch_to_main_interpreter (PyThreadState * tstate )
15311531{
1532- PyThreadState * main_tstate = tstate ;
15331532 if (_Py_IsMainInterpreter (tstate -> interp )) {
1534- /* There's no need to switch. */
1535- }
1536- else if (check_multi_interp_extensions (tstate -> interp )) {
1537- /*
1538- If the module is single-phase init then the import will fail.
1539- However, the module's init function will still get run.
1540- That means it may still store state in the shared-object/DLL
1541- address space (which never gets closed/cleared), including
1542- objects (e.g. static types).
1543-
1544- This is a problem for isolated subinterpreters since each
1545- has its own object allocator. If the loaded shared-object
1546- still holds a reference to an object after the corresponding
1547- interpreter has finalized then either we must let it leak
1548- or else any later use of that object by another interpreter
1549- (or across multiple init-fini cycles) will crash the process.
1550-
1551- We avoid the problem by first loading the module
1552- in the main interpreter.
1553-
1554- Here's another complication we avoid: the module's init
1555- function might register callbacks, whether in Python
1556- (e.g. sys.stdin, atexit) or in linked libraries.
1557- Thus we cannot just dlclose() the module
1558- in this error case.
1559- */
1560- main_tstate = PyThreadState_New (_PyInterpreterState_Main ());
1561- if (main_tstate == NULL ) {
1562- return NULL ;
1563- }
1564- main_tstate -> _whence = _PyThreadState_WHENCE_EXEC ;
1533+ return tstate ;
1534+ }
1535+ PyThreadState * main_tstate = PyThreadState_New (_PyInterpreterState_Main ());
1536+ if (main_tstate == NULL ) {
1537+ return NULL ;
1538+ }
1539+ main_tstate -> _whence = _PyThreadState_WHENCE_EXEC ;
15651540#ifndef NDEBUG
1566- PyThreadState * old_tstate = PyThreadState_Swap (main_tstate );
1567- assert (old_tstate == tstate );
1541+ PyThreadState * old_tstate = PyThreadState_Swap (main_tstate );
1542+ assert (old_tstate == tstate );
15681543#else
1569- (void )PyThreadState_Swap (main_tstate );
1544+ (void )PyThreadState_Swap (main_tstate );
15701545#endif
1571- }
15721546 return main_tstate ;
15731547}
15741548
@@ -1924,27 +1898,58 @@ import_run_extension(PyThreadState *tstate, PyModInitFunction p0,
19241898 * multi-phase init until after we call its init function. Even
19251899 * in isolated interpreters (that do not support single-phase init),
19261900 * the init function will run without restriction. For multi-phase
1927- * init modules that isn't a problem because the init function runs
1928- * PyModuleDef_Init() on the module's def and then returns it.
1901+ * init modules that isn't a problem because the init function only
1902+ * runs PyModuleDef_Init() on the module's def and then returns it.
19291903 *
19301904 * However, for single-phase init the module's init function will
19311905 * create the module, create other objects (and allocate other
19321906 * memory), populate it and its module state, and initialze static
19331907 * types. Some modules store other objects and data in global C
19341908 * variables and register callbacks with the runtime/stdlib or
1935- * event external libraries. That's a problem for isolated
1936- * interpreters since all of that happens and only then will
1937- * the import fail. Memory will leak, callbacks will still
1938- * get used, and sometimes there will be memory access
1939- * violations and use-after-free crashes.
1909+ * even external libraries (which is part of why we can't just
1910+ * dlclose() the module in the error case). That's a problem
1911+ * for isolated interpreters since all of the above happens
1912+ * and only then * will the import fail. Memory will leak,
1913+ * callbacks will still get used, and sometimes there
1914+ * will be crashes (memory access violations
1915+ * and use-after-free).
1916+ *
1917+ * To put it another way, if the module is single-phase init
1918+ * then the import will probably break interpreter isolation
1919+ * and should fail ASAP. However, the module's init function
1920+ * will still get run. That means it may still store state
1921+ * in the shared-object/DLL address space (which never gets
1922+ * closed/cleared), including objects (e.g. static types).
1923+ * This is a problem for isolated subinterpreters since each
1924+ * has its own object allocator. If the loaded shared-object
1925+ * still holds a reference to an object after the corresponding
1926+ * interpreter has finalized then either we must let it leak
1927+ * or else any later use of that object by another interpreter
1928+ * (or across multiple init-fini cycles) will crash the process.
19401929 *
1941- * To avoid that, we make sure the module's init function is always
1942- * run first with the main interpreter active. If it was already
1943- * the main interpreter then we can continue loading the module
1944- * like normal. Otherwise, right after the init function, we switch
1945- * back to the subinterpreter, check for single-phase init, and
1946- * then continue loading like normal. */
1947- PyThreadState * main_tstate = maybe_switch_to_main_interpreter (tstate );
1930+ * To avoid all of that, we make sure the module's init function
1931+ * is always run first with the main interpreter active. If it was
1932+ * already the main interpreter then we can continue loading the
1933+ * module like normal. Otherwise, right after the init function,
1934+ * we take care of some import state bookkeeping, switch back
1935+ * to the subinterpreter, check for single-phase init,
1936+ * and then continue loading like normal. */
1937+
1938+ PyThreadState * main_tstate = NULL ;
1939+ if (!_Py_IsMainInterpreter (tstate -> interp )) {
1940+ /* We *could* leave in place a legacy interpreter here
1941+ * (one that shares obmalloc/GIL with main interp),
1942+ * but there isn't a big advantage, we anticipate
1943+ * such interpreters will be increasingly uncommon,
1944+ * and the code is a bit simpler if we always switch
1945+ * to the main interpreter. */
1946+ main_tstate = switch_to_main_interpreter (tstate );
1947+ if (main_tstate == NULL ) {
1948+ return NULL ;
1949+ }
1950+ assert (main_tstate != tstate );
1951+ // XXX Get import lock.
1952+ }
19481953
19491954 struct _Py_ext_module_loader_result res ;
19501955 int rc = _PyImport_RunModInitFunc (p0 , info , & res );
@@ -1984,6 +1989,8 @@ import_run_extension(PyThreadState *tstate, PyModInitFunction p0,
19841989 if (res .kind == _Py_ext_module_kind_MULTIPHASE ) {
19851990 assert_multiphase_def (def );
19861991 assert (mod == NULL );
1992+ /* Note that we cheat a little by not repeating the calls
1993+ * to _PyImport_GetModInitFunc() and _PyImport_RunModInitFunc(). */
19871994 mod = PyModule_FromDefAndSpec (def , spec );
19881995 if (mod == NULL ) {
19891996 goto error ;
0 commit comments