diff options
Diffstat (limited to 'Python/importdl.c')
-rw-r--r-- | Python/importdl.c | 101 |
1 files changed, 55 insertions, 46 deletions
diff --git a/Python/importdl.c b/Python/importdl.c index f2ad95f..cc70a6d 100644 --- a/Python/importdl.c +++ b/Python/importdl.c @@ -179,17 +179,12 @@ _Py_ext_module_loader_info_init_from_spec( } -PyObject * -_PyImport_LoadDynamicModuleWithSpec(struct _Py_ext_module_loader_info *info, - PyObject *spec, FILE *fp) +PyModInitFunction +_PyImport_GetModInitFunc(struct _Py_ext_module_loader_info *info, + FILE *fp) { - PyObject *m = NULL; const char *name_buf = PyBytes_AS_STRING(info->name_encoded); - const char *oldcontext; dl_funcptr exportfunc; - PyModInitFunction p0; - PyModuleDef *def; - #ifdef MS_WINDOWS exportfunc = _PyImport_FindSharedFuncptrWindows( info->hook_prefix, name_buf, info->filename, fp); @@ -213,16 +208,29 @@ _PyImport_LoadDynamicModuleWithSpec(struct _Py_ext_module_loader_info *info, Py_DECREF(msg); } } - goto error; + return NULL; } - p0 = (PyModInitFunction)exportfunc; + return (PyModInitFunction)exportfunc; +} + +int +_PyImport_RunModInitFunc(PyModInitFunction p0, + struct _Py_ext_module_loader_info *info, + struct _Py_ext_module_loader_result *p_res) +{ + struct _Py_ext_module_loader_result res = {0}; + const char *name_buf = PyBytes_AS_STRING(info->name_encoded); + + /* Call the module init function. */ /* Package context is needed for single-phase init */ - oldcontext = _PyImport_SwapPackageContext(info->newcontext); - m = p0(); + const char *oldcontext = _PyImport_SwapPackageContext(info->newcontext); + PyObject *m = p0(); _PyImport_SwapPackageContext(oldcontext); + /* Validate the result (and populate "res". */ + if (m == NULL) { if (!PyErr_Occurred()) { PyErr_Format( @@ -236,9 +244,13 @@ _PyImport_LoadDynamicModuleWithSpec(struct _Py_ext_module_loader_info *info, PyExc_SystemError, "initialization of %s raised unreported exception", name_buf); + /* We would probably be correct to decref m here, + * but we weren't doing so before, + * so we stick with doing nothing. */ m = NULL; goto error; } + if (Py_IS_TYPE(m, NULL)) { /* This can happen when a PyModuleDef is returned without calling * PyModuleDef_Init on it @@ -246,55 +258,52 @@ _PyImport_LoadDynamicModuleWithSpec(struct _Py_ext_module_loader_info *info, PyErr_Format(PyExc_SystemError, "init function of %s returned uninitialized object", name_buf); + /* Likewise, decref'ing here makes sense. However, the original + * code has a note about "prevent segfault in DECREF", + * so we play it safe and leave it alone. */ m = NULL; /* prevent segfault in DECREF */ goto error; } - if (PyObject_TypeCheck(m, &PyModuleDef_Type)) { - return PyModule_FromDefAndSpec((PyModuleDef*)m, spec); - } - /* Fall back to single-phase init mechanism */ - - if (_PyImport_CheckSubinterpIncompatibleExtensionAllowed(name_buf) < 0) { - goto error; + if (PyObject_TypeCheck(m, &PyModuleDef_Type)) { + /* multi-phase init */ + res.def = (PyModuleDef *)m; + /* Run PyModule_FromDefAndSpec() to finish loading the module. */ } - - if (info->hook_prefix == nonascii_prefix) { - /* don't allow legacy init for non-ASCII module names */ + else if (info->hook_prefix == nonascii_prefix) { + /* It should have been multi-phase init? */ + /* Don't allow legacy init for non-ASCII module names. */ PyErr_Format( PyExc_SystemError, "initialization of %s did not return PyModuleDef", name_buf); - goto error; - } - - /* Remember pointer to module init function. */ - def = PyModule_GetDef(m); - if (def == NULL) { - PyErr_Format(PyExc_SystemError, - "initialization of %s did not return an extension " - "module", name_buf); - goto error; - } - def->m_base.m_init = p0; - - /* Remember the filename as the __file__ attribute */ - if (PyModule_AddObjectRef(m, "__file__", info->filename) < 0) { - PyErr_Clear(); /* Not important enough to report */ + Py_DECREF(m); + return -1; } + else { + /* single-phase init (legacy) */ + res.module = m; - PyObject *modules = PyImport_GetModuleDict(); - if (_PyImport_FixupExtensionObject( - m, info->name, info->filename, modules) < 0) - { - goto error; + res.def = PyModule_GetDef(m); + if (res.def == NULL) { + PyErr_Clear(); + PyErr_Format(PyExc_SystemError, + "initialization of %s did not return an extension " + "module", name_buf); + goto error; + } } - return m; + assert(!PyErr_Occurred()); + *p_res = res; + return 0; error: - Py_XDECREF(m); - return NULL; + assert(PyErr_Occurred()); + Py_CLEAR(res.module); + res.def = NULL; + *p_res = res; + return -1; } #endif /* HAVE_DYNAMIC_LOADING */ |