@@ -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+ */
564579PyObject *
565580PyImport_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);
888907static PyObject *
889908load_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