]> granicus.if.org Git - python/commitdiff
Fix [ 771097 ] frozen programs fail due to implicit import of "warnings".
authorMark Hammond <mhammond@skippinet.com.au>
Tue, 15 Jul 2003 23:03:55 +0000 (23:03 +0000)
committerMark Hammond <mhammond@skippinet.com.au>
Tue, 15 Jul 2003 23:03:55 +0000 (23:03 +0000)
If the initial import of warnings fails, clear the error.  When the module
is actually needed, if the original import failed, see if it has managed
to find its way to sys.modules yet and if so, remember it.

Python/errors.c
Python/pythonrun.c

index d43501bbe75b888fbff395e37b5680f371331374..a40844e7fe51c796b6349af2de52e22c4f8c65ca 100644 (file)
@@ -599,16 +599,17 @@ PyErr_WriteUnraisable(PyObject *obj)
        Py_XDECREF(tb);
 }
 
-extern PyObject *PyModule_WarningsModule;
+extern PyObject *PyModule_GetWarningsModule();
 
 /* Function to issue a warning message; may raise an exception. */
 int
 PyErr_Warn(PyObject *category, char *message)
 {
        PyObject *dict, *func = NULL;
+       PyObject *warnings_module = PyModule_GetWarningsModule();
 
-       if (PyModule_WarningsModule != NULL) {
-               dict = PyModule_GetDict(PyModule_WarningsModule);
+       if (warnings_module != NULL) {
+               dict = PyModule_GetDict(warnings_module);
                func = PyDict_GetItemString(dict, "warn");
        }
        if (func == NULL) {
index a8dedde7c11d877b2f93df684d0210d0c1094a6b..fb40e8f22ea410dae1eb9b3db7d59366aeddc935 100644 (file)
@@ -69,9 +69,38 @@ int Py_IgnoreEnvironmentFlag; /* e.g. PYTHONPATH, PYTHONHOME */
 int _Py_QnewFlag = 0;
 
 /* Reference to 'warnings' module, to avoid importing it
-   on the fly when the import lock may be held.  See 683658
+   on the fly when the import lock may be held.  See 683658/771097
 */
-PyObject *PyModule_WarningsModule = NULL;
+static PyObject *warnings_module = NULL;
+
+/* Returns a borrowed reference to the 'warnings' module, or NULL.
+   If the module is returned, it is guaranteed to have been obtained
+   without acquiring the import lock
+*/
+PyObject *PyModule_GetWarningsModule()
+{
+       PyObject *typ, *val, *tb;
+       PyObject *all_modules;
+       /* If we managed to get the module at init time, just use it */
+       if (warnings_module)
+               return warnings_module;
+       /* If it wasn't available at init time, it may be available
+          now in sys.modules (common scenario is frozen apps: import
+          at init time fails, but the frozen init code sets up sys.path
+          correctly, then does an implicit import of warnings for us
+       */
+       /* Save and restore any exceptions */
+       PyErr_Fetch(&typ, &val, &tb);
+
+       all_modules = PySys_GetObject("__modules__");
+       if (all_modules) {
+               warnings_module = PyDict_GetItemString(all_modules, "warnings");
+               /* We keep a ref in the global */
+               Py_XINCREF(warnings_module);
+       }
+       PyErr_Restore(typ, val, tb);
+       return warnings_module;
+}
 
 static int initialized = 0;
 
@@ -190,7 +219,9 @@ Py_Initialize(void)
        _PyGILState_Init(interp, tstate);
 #endif /* WITH_THREAD */
 
-       PyModule_WarningsModule = PyImport_ImportModule("warnings");
+       warnings_module = PyImport_ImportModule("warnings");
+       if (!warnings_module)
+               PyErr_Clear();
 
 #if defined(Py_USING_UNICODE) && defined(HAVE_LANGINFO_H) && defined(CODESET)
        /* On Unix, set the file system encoding according to the
@@ -262,8 +293,8 @@ Py_Finalize(void)
        PyOS_FiniInterrupts();
 
        /* drop module references we saved */
-       Py_XDECREF(PyModule_WarningsModule);
-       PyModule_WarningsModule = NULL;
+       Py_XDECREF(warnings_module);
+       warnings_module = NULL;
 
        /* Collect garbage.  This may call finalizers; it's nice to call these
           before all modules are destroyed. */