diff --git a/Include/import.h b/Include/import.h index 46c0d8e..75281b8 100644 --- a/Include/import.h +++ b/Include/import.h @@ -36,9 +36,16 @@ PyAPI_FUNC(PyObject *) PyImport_ExecCodeModuleObject( PyObject *cpathname ); PyAPI_FUNC(PyObject *) PyImport_GetModuleDict(void); +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyImport_GetModuleDict(PyThreadState *tstate); +PyAPI_FUNC(void) _PyImport_EnsureInitialized(PyInterpreterState *interp); +#endif PyAPI_FUNC(PyObject *) PyImport_AddModuleObject( PyObject *name ); +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyImport_AddModuleObject(PyObject *, PyObject *); +#endif PyAPI_FUNC(PyObject *) PyImport_AddModule( const char *name /* UTF-8 encoded string */ ); @@ -89,14 +96,20 @@ PyAPI_FUNC(int) _PyImport_ReleaseLock(void); PyAPI_FUNC(void) _PyImport_ReInitLock(void); PyAPI_FUNC(PyObject *) _PyImport_FindBuiltin( - const char *name /* UTF-8 encoded string */ + const char *name, /* UTF-8 encoded string */ + PyObject *modules ); PyAPI_FUNC(PyObject *) _PyImport_FindExtensionObject(PyObject *, PyObject *); +PyAPI_FUNC(PyObject *) _PyImport_FindExtensionObjectEx(PyObject *, PyObject *, + PyObject *); PyAPI_FUNC(int) _PyImport_FixupBuiltin( PyObject *mod, - const char *name /* UTF-8 encoded string */ + const char *name, /* UTF-8 encoded string */ + PyObject *modules ); PyAPI_FUNC(int) _PyImport_FixupExtensionObject(PyObject*, PyObject *, PyObject *); +PyAPI_FUNC(int) _PyImport_FixupExtensionObjectEx(PyObject*, PyObject *, + PyObject *, PyObject *); struct _inittab { const char *name; /* ASCII encoded string */ diff --git a/Include/modsupport.h b/Include/modsupport.h index 833e33d..06dcfb0 100644 --- a/Include/modsupport.h +++ b/Include/modsupport.h @@ -151,6 +151,10 @@ PyAPI_FUNC(int) PyModule_ExecDef(PyObject *module, PyModuleDef *def); PyAPI_FUNC(PyObject *) PyModule_Create2(struct PyModuleDef*, int apiver); +#ifndef Py_LIMITED_API +PyAPI_FUNC(PyObject *) _PyModule_Create2(struct PyModuleDef*, + int apiver); +#endif #ifdef Py_LIMITED_API #define PyModule_Create(module) \ diff --git a/Include/pystate.h b/Include/pystate.h index afc3c0c..b2a4b4c 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -28,7 +28,6 @@ typedef struct _is { struct _is *next; struct _ts *tstate_head; - PyObject *modules; PyObject *modules_by_index; PyObject *sysdict; PyObject *builtins; diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index dcae1c4..5a6b618 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -161,11 +161,16 @@ _add_methods_to_object(PyObject *module, PyObject *name, PyMethodDef *functions) PyObject * PyModule_Create2(struct PyModuleDef* module, int module_api_version) { + _PyImport_EnsureInitialized(PyThreadState_GET()->interp); + return _PyModule_Create2(module, module_api_version); +} + +PyObject * +_PyModule_Create2(struct PyModuleDef* module, int module_api_version) +{ const char* name; PyModuleObject *m; - PyInterpreterState *interp = PyThreadState_Get()->interp; - if (interp->modules == NULL) - Py_FatalError("Python import machinery not initialized"); + if (!PyModuleDef_Init(module)) return NULL; name = module->m_name; diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 1960c1a..9c97ab9 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3809,7 +3809,6 @@ import_copyreg(void) { PyObject *copyreg_str; PyObject *copyreg_module; - PyInterpreterState *interp = PyThreadState_GET()->interp; _Py_IDENTIFIER(copyreg); copyreg_str = _PyUnicode_FromId(&PyId_copyreg); @@ -3821,7 +3820,8 @@ import_copyreg(void) by storing a reference to the cached module in a static variable, but this broke when multiple embedded interpreters were in use (see issue #17408 and #19088). */ - copyreg_module = PyDict_GetItemWithError(interp->modules, copyreg_str); + PyObject *modules = PyImport_GetModuleDict(); + copyreg_module = PyDict_GetItemWithError(modules, copyreg_str); if (copyreg_module != NULL) { Py_INCREF(copyreg_module); return copyreg_module; diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index cee013f..1f648cf 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -2654,7 +2654,7 @@ _PyBuiltin_Init(void) PyType_Ready(&PyZip_Type) < 0) return NULL; - mod = PyModule_Create(&builtinsmodule); + mod = _PyModule_Create2(&builtinsmodule, PYTHON_API_VERSION); if (mod == NULL) return NULL; dict = PyModule_GetDict(mod); diff --git a/Python/ceval.c b/Python/ceval.c index 3e74819..a67f22c 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -308,8 +308,8 @@ PyEval_ReInitThreads(void) /* Update the threading module with the new state. */ - threading = PyMapping_GetItemString(current_tstate->interp->modules, - "threading"); + PyObject *modules = _PyImport_GetModuleDict(current_tstate); + threading = PyMapping_GetItemString(modules, "threading"); if (threading == NULL) { /* threading not imported */ PyErr_Clear(); diff --git a/Python/import.c b/Python/import.c index dfdd940..983b73b 100644 --- a/Python/import.c +++ b/Python/import.c @@ -302,12 +302,42 @@ _PyImport_Fini(void) /* Helper for sys */ PyObject * +_PyImport_GetModuleDict(PyThreadState *tstate) +{ + if (tstate->interp->sysdict == NULL) + Py_FatalError("_PyImport_GetModuleDict: no sys module!"); + + _Py_IDENTIFIER(modules); + PyObject *modules = _PyDict_GetItemId(tstate->interp->sysdict, + &PyId_modules); + if (modules == NULL) + Py_FatalError("lost sys.modules"); + return modules; +} + +PyObject * PyImport_GetModuleDict(void) { - PyInterpreterState *interp = PyThreadState_GET()->interp; - if (interp->modules == NULL) - Py_FatalError("PyImport_GetModuleDict: no module dictionary!"); - return interp->modules; + return _PyImport_GetModuleDict(PyThreadState_GET()); +} + +/* In some corner cases it is important to be sure that the import + machinery has been initialized (or not cleaned up yet). For + example, see issue #4236 and PyModule_Create2(). */ + +void +_PyImport_EnsureInitialized(PyInterpreterState *interp) +{ + if (interp->sysdict == NULL) + goto notinitialized; + _Py_IDENTIFIER(modules); + PyObject *modules = _PyDict_GetItemId(interp->sysdict, &PyId_modules); + if (modules == NULL) + goto notinitialized; + return; + +notinitialized: + Py_FatalError("Python import machinery not initialized"); } @@ -337,7 +367,7 @@ PyImport_Cleanup(void) Py_ssize_t pos; PyObject *key, *value, *dict; PyInterpreterState *interp = PyThreadState_GET()->interp; - PyObject *modules = interp->modules; + PyObject *modules = PyImport_GetModuleDict(); PyObject *weaklist = NULL; const char * const *p; @@ -466,7 +496,6 @@ PyImport_Cleanup(void) /* Clear and delete the modules directory. Actual modules will still be there only if imported during the execution of some destructor. */ - interp->modules = NULL; Py_DECREF(modules); /* Once more */ @@ -527,7 +556,15 @@ int _PyImport_FixupExtensionObject(PyObject *mod, PyObject *name, PyObject *filename) { - PyObject *modules, *dict, *key; + PyObject *modules = PyImport_GetModuleDict(); + return _PyImport_FixupExtensionObjectEx(mod, name, filename, modules); +} + +int +_PyImport_FixupExtensionObjectEx(PyObject *mod, PyObject *name, + PyObject *filename, PyObject *modules) +{ + PyObject *dict, *key; struct PyModuleDef *def; int res; if (extensions == NULL) { @@ -544,7 +581,6 @@ _PyImport_FixupExtensionObject(PyObject *mod, PyObject *name, PyErr_BadInternalCall(); return -1; } - modules = PyImport_GetModuleDict(); if (PyDict_SetItem(modules, name, mod) < 0) return -1; if (_PyState_AddModule(mod, def) < 0) { @@ -576,14 +612,14 @@ _PyImport_FixupExtensionObject(PyObject *mod, PyObject *name, } int -_PyImport_FixupBuiltin(PyObject *mod, const char *name) +_PyImport_FixupBuiltin(PyObject *mod, const char *name, PyObject *modules) { int res; PyObject *nameobj; nameobj = PyUnicode_InternFromString(name); if (nameobj == NULL) return -1; - res = _PyImport_FixupExtensionObject(mod, nameobj, nameobj); + res = _PyImport_FixupExtensionObjectEx(mod, nameobj, nameobj, modules); Py_DECREF(nameobj); return res; } @@ -591,6 +627,14 @@ _PyImport_FixupBuiltin(PyObject *mod, const char *name) PyObject * _PyImport_FindExtensionObject(PyObject *name, PyObject *filename) { + PyObject *modules = PyImport_GetModuleDict(); + return _PyImport_FindExtensionObjectEx(name, filename, modules); +} + +PyObject * +_PyImport_FindExtensionObjectEx(PyObject *name, PyObject *filename, + PyObject *modules) +{ PyObject *mod, *mdict, *key; PyModuleDef* def; if (extensions == NULL) @@ -606,7 +650,7 @@ _PyImport_FindExtensionObject(PyObject *name, PyObject *filename) /* Module does not support repeated initialization */ if (def->m_base.m_copy == NULL) return NULL; - mod = PyImport_AddModuleObject(name); + mod = _PyImport_AddModuleObject(name, modules); if (mod == NULL) return NULL; mdict = PyModule_GetDict(mod); @@ -621,14 +665,14 @@ _PyImport_FindExtensionObject(PyObject *name, PyObject *filename) mod = def->m_base.m_init(); if (mod == NULL) return NULL; - if (PyDict_SetItem(PyImport_GetModuleDict(), name, mod) == -1) { + if (PyDict_SetItem(modules, name, mod) == -1) { Py_DECREF(mod); return NULL; } Py_DECREF(mod); } if (_PyState_AddModule(mod, def) < 0) { - PyDict_DelItem(PyImport_GetModuleDict(), name); + PyDict_DelItem(modules, name); Py_DECREF(mod); return NULL; } @@ -640,13 +684,13 @@ _PyImport_FindExtensionObject(PyObject *name, PyObject *filename) } PyObject * -_PyImport_FindBuiltin(const char *name) +_PyImport_FindBuiltin(const char *name, PyObject *modules) { PyObject *res, *nameobj; nameobj = PyUnicode_InternFromString(name); if (nameobj == NULL) return NULL; - res = _PyImport_FindExtensionObject(nameobj, nameobj); + res = _PyImport_FindExtensionObjectEx(nameobj, nameobj, modules); Py_DECREF(nameobj); return res; } @@ -661,6 +705,12 @@ PyObject * PyImport_AddModuleObject(PyObject *name) { PyObject *modules = PyImport_GetModuleDict(); + return _PyImport_AddModuleObject(name, modules); +} + +PyObject * +_PyImport_AddModuleObject(PyObject *name, PyObject *modules) +{ PyObject *m; if ((m = PyDict_GetItemWithError(modules, name)) != NULL && @@ -1351,7 +1401,6 @@ resolve_name(PyObject *name, PyObject *globals, int level) PyObject *abs_name; PyObject *package = NULL; PyObject *spec; - PyInterpreterState *interp = PyThreadState_GET()->interp; Py_ssize_t last_dot; PyObject *base; int level_up; @@ -1455,11 +1504,14 @@ resolve_name(PyObject *name, PyObject *globals, int level) "attempted relative import with no known parent package"); goto error; } - else if (PyDict_GetItem(interp->modules, package) == NULL) { - PyErr_Format(PyExc_SystemError, - "Parent module %R not loaded, cannot perform relative " - "import", package); - goto error; + else { + PyObject *modules = PyImport_GetModuleDict(); + if (PyDict_GetItem(modules, package) == NULL) { + PyErr_Format(PyExc_SystemError, + "Parent module %R not loaded, cannot perform relative " + "import", package); + goto error; + } } for (level_up = 1; level_up < level; level_up += 1) { @@ -1538,7 +1590,8 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, Py_INCREF(abs_name); } - mod = PyDict_GetItem(interp->modules, abs_name); + PyObject *modules = PyImport_GetModuleDict(); + mod = PyDict_GetItem(modules, abs_name); if (mod == Py_None) { PyObject *msg = PyUnicode_FromFormat("import of %R halted; " "None in sys.modules", abs_name); @@ -1644,7 +1697,8 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, goto error; } - final_mod = PyDict_GetItem(interp->modules, to_return); + PyObject *modules = PyImport_GetModuleDict(); + final_mod = PyDict_GetItem(modules, to_return); Py_DECREF(to_return); if (final_mod == NULL) { PyErr_Format(PyExc_KeyError, diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 5b5cc2b..4072e1f 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -378,10 +378,19 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib) if (!_PyFloat_Init()) Py_FatalError("Py_Initialize: can't init float"); - interp->modules = PyDict_New(); - if (interp->modules == NULL) + PyObject *modules = PyDict_New(); + if (modules == NULL) Py_FatalError("Py_Initialize: can't make modules dictionary"); + sysmod = _PySys_Init(); + if (sysmod == NULL) + Py_FatalError("Py_Initialize: can't initialize sys"); + interp->sysdict = PyModule_GetDict(sysmod); + if (interp->sysdict == NULL) + Py_FatalError("Py_Initialize: can't initialize sys dict"); + Py_INCREF(interp->sysdict); + _PyImport_FixupBuiltin(sysmod, "sys", modules); + /* Init Unicode implementation; relies on the codec registry */ if (_PyUnicode_Init() < 0) Py_FatalError("Py_Initialize: can't initialize unicode"); @@ -391,7 +400,7 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib) bimod = _PyBuiltin_Init(); if (bimod == NULL) Py_FatalError("Py_Initialize: can't initialize builtins modules"); - _PyImport_FixupBuiltin(bimod, "builtins"); + _PyImport_FixupBuiltin(bimod, "builtins", modules); interp->builtins = PyModule_GetDict(bimod); if (interp->builtins == NULL) Py_FatalError("Py_Initialize: can't initialize builtins dict"); @@ -400,17 +409,9 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib) /* initialize builtin exceptions */ _PyExc_Init(bimod); - sysmod = _PySys_Init(); - if (sysmod == NULL) - Py_FatalError("Py_Initialize: can't initialize sys"); - interp->sysdict = PyModule_GetDict(sysmod); - if (interp->sysdict == NULL) - Py_FatalError("Py_Initialize: can't initialize sys dict"); - Py_INCREF(interp->sysdict); - _PyImport_FixupBuiltin(sysmod, "sys"); PySys_SetPath(Py_GetPath()); PyDict_SetItemString(interp->sysdict, "modules", - interp->modules); + modules); /* Set up a preliminary stderr printer until we have enough infrastructure for the io module in place. */ @@ -792,9 +793,19 @@ Py_NewInterpreter(void) /* XXX The following is lax in error checking */ - interp->modules = PyDict_New(); + PyObject *modules = PyDict_New(); + if (modules == NULL) + Py_FatalError("Py_NewInterpreter: can't make modules dictionary"); - bimod = _PyImport_FindBuiltin("builtins"); + sysmod = _PyImport_FindBuiltin("sys", modules); + if (sysmod != NULL) { + interp->sysdict = PyModule_GetDict(sysmod); + if (interp->sysdict == NULL) + goto handle_error; + Py_INCREF(interp->sysdict); + } + + bimod = _PyImport_FindBuiltin("builtins", modules); if (bimod != NULL) { interp->builtins = PyModule_GetDict(bimod); if (interp->builtins == NULL) @@ -805,17 +816,13 @@ Py_NewInterpreter(void) /* initialize builtin exceptions */ _PyExc_Init(bimod); - sysmod = _PyImport_FindBuiltin("sys"); if (bimod != NULL && sysmod != NULL) { PyObject *pstderr; - interp->sysdict = PyModule_GetDict(sysmod); - if (interp->sysdict == NULL) - goto handle_error; - Py_INCREF(interp->sysdict); PySys_SetPath(Py_GetPath()); PyDict_SetItemString(interp->sysdict, "modules", - interp->modules); + modules); + /* Set up a preliminary stderr printer until we have enough infrastructure for the io module in place. */ pstderr = PyFile_NewStdPrinter(fileno(stderr)); @@ -1490,9 +1497,8 @@ wait_for_thread_shutdown(void) #ifdef WITH_THREAD _Py_IDENTIFIER(_shutdown); PyObject *result; - PyThreadState *tstate = PyThreadState_GET(); - PyObject *threading = PyMapping_GetItemString(tstate->interp->modules, - "threading"); + PyObject *modules = PyImport_GetModuleDict(); + PyObject *threading = PyMapping_GetItemString(modules, "threading"); if (threading == NULL) { /* threading not imported */ PyErr_Clear(); diff --git a/Python/pystate.c b/Python/pystate.c index 65c244e..def6e12 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -78,7 +78,6 @@ PyInterpreterState_New(void) if (head_mutex == NULL) Py_FatalError("Can't initialize threads for interpreter"); #endif - interp->modules = NULL; interp->modules_by_index = NULL; interp->sysdict = NULL; interp->builtins = NULL; @@ -121,7 +120,6 @@ PyInterpreterState_Clear(PyInterpreterState *interp) Py_CLEAR(interp->codec_search_path); Py_CLEAR(interp->codec_search_cache); Py_CLEAR(interp->codec_error_registry); - Py_CLEAR(interp->modules); Py_CLEAR(interp->modules_by_index); Py_CLEAR(interp->sysdict); Py_CLEAR(interp->builtins); diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 5dd0d10..1a57dc8 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -163,8 +163,9 @@ static PyObject * sys_displayhook(PyObject *self, PyObject *o) { PyObject *outf; - PyInterpreterState *interp = PyThreadState_GET()->interp; - PyObject *modules = interp->modules; + PyObject *modules = PyImport_GetModuleDict(); + if (modules == NULL) + return NULL; PyObject *builtins; static PyObject *newline = NULL; int err; @@ -1888,7 +1889,7 @@ _PySys_Init(void) PyObject *m, *sysdict, *version_info; int res; - m = PyModule_Create(&sysmodule); + m = _PyModule_Create2(&sysmodule, PYTHON_API_VERSION); if (m == NULL) return NULL; sysdict = PyModule_GetDict(m);