Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1cd7017

Browse files
committed
PyImport_ExecCodeModuleEx(): remove module from sys.modules in error cases.
PyImport_ReloadModule(): restore the module to sys.modules in error cases. load_package(): semantic-neutral refactoring from an earlier stab at this patch; giving it a common error exit made the code easier to follow, so retaining that part. _RemoveModule(): new little utility to delete a key from sys.modules.
1 parent 94f9b86 commit 1cd7017

1 file changed

Lines changed: 46 additions & 16 deletions

File tree

Python/import.c

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -557,10 +557,25 @@ PyImport_AddModule(char *name)
557557
return m;
558558
}
559559

560+
/* Remove name from sys.modules, if it's there. */
561+
static void
562+
_RemoveModule(const char *name)
563+
{
564+
PyObject *modules = PyImport_GetModuleDict();
565+
if (PyDict_GetItemString(modules, name) == NULL)
566+
return;
567+
if (PyDict_DelItemString(modules, name) < 0)
568+
Py_FatalError("import: deleting existing key in"
569+
"sys.modules failed");
570+
}
560571

561572
/* Execute a code object in a module and return the module object
562-
WITH INCREMENTED REFERENCE COUNT */
563-
573+
* WITH INCREMENTED REFERENCE COUNT. If an error occurs, name is
574+
* removed from sys.modules, to avoid leaving damaged module objects
575+
* in sys.modules. The caller may wish to restore the original
576+
* module object (if any) in this case; PyImport_ReloadModule is an
577+
* example.
578+
*/
564579
PyObject *
565580
PyImport_ExecCodeModule(char *name, PyObject *co)
566581
{
@@ -582,7 +597,7 @@ PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname)
582597
if (PyDict_GetItemString(d, "__builtins__") == NULL) {
583598
if (PyDict_SetItemString(d, "__builtins__",
584599
PyEval_GetBuiltins()) != 0)
585-
return NULL;
600+
goto error;
586601
}
587602
/* Remember the filename as the __file__ attribute */
588603
v = NULL;
@@ -601,7 +616,7 @@ PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname)
601616

602617
v = PyEval_EvalCode((PyCodeObject *)co, d, d);
603618
if (v == NULL)
604-
return NULL;
619+
goto error;
605620
Py_DECREF(v);
606621

607622
if ((m = PyDict_GetItemString(modules, name)) == NULL) {
@@ -614,6 +629,10 @@ PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname)
614629
Py_INCREF(m);
615630

616631
return m;
632+
633+
error:
634+
_RemoveModule(name);
635+
return NULL;
617636
}
618637

619638

@@ -888,7 +907,9 @@ static struct _frozen *find_frozen(char *name);
888907
static PyObject *
889908
load_package(char *name, char *pathname)
890909
{
891-
PyObject *m, *d, *file, *path;
910+
PyObject *m, *d;
911+
PyObject *file = NULL;
912+
PyObject *path = NULL;
892913
int err;
893914
char buf[MAXPATHLEN+1];
894915
FILE *fp = NULL;
@@ -903,19 +924,15 @@ load_package(char *name, char *pathname)
903924
d = PyModule_GetDict(m);
904925
file = PyString_FromString(pathname);
905926
if (file == NULL)
906-
return NULL;
927+
goto error;
907928
path = Py_BuildValue("[O]", file);
908-
if (path == NULL) {
909-
Py_DECREF(file);
910-
return NULL;
911-
}
929+
if (path == NULL)
930+
goto error;
912931
err = PyDict_SetItemString(d, "__file__", file);
913932
if (err == 0)
914933
err = PyDict_SetItemString(d, "__path__", path);
915-
if (err != 0) {
916-
m = NULL;
917-
goto cleanup;
918-
}
934+
if (err != 0)
935+
goto error;
919936
buf[0] = '\0';
920937
fdp = find_module(name, "__init__", path, buf, sizeof(buf), &fp, NULL);
921938
if (fdp == NULL) {
@@ -930,6 +947,10 @@ load_package(char *name, char *pathname)
930947
m = load_module(name, fp, buf, fdp->type, NULL);
931948
if (fp != NULL)
932949
fclose(fp);
950+
goto cleanup;
951+
952+
error:
953+
m = NULL;
933954
cleanup:
934955
Py_XDECREF(path);
935956
Py_XDECREF(file);
@@ -2234,6 +2255,7 @@ PyImport_ReloadModule(PyObject *m)
22342255
char buf[MAXPATHLEN+1];
22352256
struct filedescr *fdp;
22362257
FILE *fp = NULL;
2258+
PyObject *newm;
22372259

22382260
if (m == NULL || !PyModule_Check(m)) {
22392261
PyErr_SetString(PyExc_TypeError,
@@ -2275,10 +2297,18 @@ PyImport_ReloadModule(PyObject *m)
22752297
Py_XDECREF(path);
22762298
if (fdp == NULL)
22772299
return NULL;
2278-
m = load_module(name, fp, buf, fdp->type, NULL);
2300+
newm = load_module(name, fp, buf, fdp->type, NULL);
22792301
if (fp)
22802302
fclose(fp);
2281-
return m;
2303+
if (newm == NULL) {
2304+
/* load_module probably removed name from modules because of
2305+
* the error. Put back the original module object. We're
2306+
* going to return NULL in this case regardless of whether
2307+
* replacing name succeeds, so the return value is ignored.
2308+
*/
2309+
PyDict_SetItemString(modules, name, m);
2310+
}
2311+
return newm;
22822312
}
22832313

22842314

0 commit comments

Comments
 (0)