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

Skip to content

Commit a43fd0c

Browse files
committed
Fix bug 683658 - PyErr_Warn may cause import deadlock.
1 parent 4ccf3e1 commit a43fd0c

3 files changed

Lines changed: 19 additions & 6 deletions

File tree

Lib/warnings.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
"""Python part of the warnings subsystem."""
22

3+
# Note: function level imports should *not* be used
4+
# in this module as it may cause import lock deadlock.
5+
# See bug 683658.
36
import sys, re, types
7+
import linecache
48

59
__all__ = ["warn", "showwarning", "formatwarning", "filterwarnings",
610
"resetwarnings"]
@@ -114,7 +118,6 @@ def showwarning(message, category, filename, lineno, file=None):
114118

115119
def formatwarning(message, category, filename, lineno):
116120
"""Function to format a warning the standard way."""
117-
import linecache
118121
s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
119122
line = linecache.getline(filename, lineno).strip()
120123
if line:

Python/errors.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -600,18 +600,17 @@ PyErr_WriteUnraisable(PyObject *obj)
600600
Py_XDECREF(tb);
601601
}
602602

603+
extern PyObject *PyModule_WarningsModule;
603604

604605
/* Function to issue a warning message; may raise an exception. */
605606
int
606607
PyErr_Warn(PyObject *category, char *message)
607608
{
608-
PyObject *mod, *dict, *func = NULL;
609+
PyObject *dict, *func = NULL;
609610

610-
mod = PyImport_ImportModule("warnings");
611-
if (mod != NULL) {
612-
dict = PyModule_GetDict(mod);
611+
if (PyModule_WarningsModule != NULL) {
612+
dict = PyModule_GetDict(PyModule_WarningsModule);
613613
func = PyDict_GetItemString(dict, "warn");
614-
Py_DECREF(mod);
615614
}
616615
if (func == NULL) {
617616
PySys_WriteStderr("warning: %s\n", message);

Python/pythonrun.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ int Py_IgnoreEnvironmentFlag; /* e.g. PYTHONPATH, PYTHONHOME */
6060
true divisions (which they will be in 2.3). */
6161
int _Py_QnewFlag = 0;
6262

63+
/* Reference to 'warnings' module, to avoid importing it
64+
on the fly when the import lock may be held. See 683658
65+
*/
66+
PyObject *PyModule_WarningsModule = NULL;
67+
6368
static int initialized = 0;
6469

6570
/* API to access the initialized flag -- useful for esoteric use */
@@ -169,6 +174,8 @@ Py_Initialize(void)
169174

170175
_PyImportHooks_Init();
171176

177+
PyModule_WarningsModule = PyImport_ImportModule("warnings");
178+
172179
initsigs(); /* Signal handling stuff, including initintr() */
173180

174181
initmain(); /* Module __main__ */
@@ -225,6 +232,10 @@ Py_Finalize(void)
225232
/* Cleanup Codec registry */
226233
_PyCodecRegistry_Fini();
227234

235+
/* drop module references we saved */
236+
Py_XDECREF(PyModule_WarningsModule);
237+
PyModule_WarningsModule = NULL;
238+
228239
/* Destroy all modules */
229240
PyImport_Cleanup();
230241

0 commit comments

Comments
 (0)