summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2001-01-21 03:40:37 (GMT)
committerTim Peters <tim.peters@gmail.com>2001-01-21 03:40:37 (GMT)
commit384fd106e89ec859ace7c098620aad8ce2c2abaa (patch)
treec64de17c61b9e6b6f9fb77853611c544e1c6ac3d
parenteccd02a40d0921fc2953213e71da8a3a79d00e17 (diff)
downloadcpython-384fd106e89ec859ace7c098620aad8ce2c2abaa.zip
cpython-384fd106e89ec859ace7c098620aad8ce2c2abaa.tar.gz
cpython-384fd106e89ec859ace7c098620aad8ce2c2abaa.tar.bz2
Bug #128475: mimetools.encode (sometimes) fails when called from a thread.
pythonrun.c: In Py_Finalize, don't reset the initialized flag until after the exit funcs have run. atexit.py: in _run_exitfuncs, mutate the list of pending calls in a threadsafe way. This wasn't a contributor to bug 128475, it just burned my eyeballs when looking at that bug.
-rw-r--r--Lib/atexit.py3
-rw-r--r--Python/pythonrun.c11
2 files changed, 11 insertions, 3 deletions
diff --git a/Lib/atexit.py b/Lib/atexit.py
index bcf7e54..61f2458 100644
--- a/Lib/atexit.py
+++ b/Lib/atexit.py
@@ -16,9 +16,8 @@ def _run_exitfuncs():
"""
while _exithandlers:
- func, targs, kargs = _exithandlers[-1]
+ func, targs, kargs = _exithandlers.pop()
apply(func, targs, kargs)
- _exithandlers.remove(_exithandlers[-1])
def register(func, *targs, **kargs):
"""register a function to be executed upon normal program termination
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index ff2142b..4c94f9b 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -181,9 +181,18 @@ Py_Finalize(void)
if (!initialized)
return;
- initialized = 0;
+ /* The interpreter is still entirely intact at this point, and the
+ * exit funcs may be relying on that. In particular, if some thread
+ * or exit func is still waiting to do an import, the import machinery
+ * expects Py_IsInitialized() to return true. So don't say the
+ * interpreter is uninitialized until after the exit funcs have run.
+ * Note that Threading.py uses an exit func to do a join on all the
+ * threads created thru it, so this also protects pending imports in
+ * the threads created via Threading.
+ */
call_sys_exitfunc();
+ initialized = 0;
/* Get current thread state and interpreter pointer */
tstate = PyThreadState_Get();