Issue #1722344: threading._shutdown() is now called in Py_Finalize(), which

fixes the problem of some exceptions being thrown at shutdown when the
interpreter is killed. Patch by Adam Olsen.
This commit is contained in:
Antoine Pitrou 2009-10-20 21:29:37 +00:00
parent a7a52ab7ee
commit efb60c0ceb
5 changed files with 59 additions and 29 deletions

View File

@ -306,6 +306,30 @@ def func(frame, event, arg):
self.assertFalse(rc == 2, "interpreted was blocked") self.assertFalse(rc == 2, "interpreted was blocked")
self.assertTrue(rc == 0, "Unexpected error") self.assertTrue(rc == 0, "Unexpected error")
def test_join_nondaemon_on_shutdown(self):
# Issue 1722344
# Raising SystemExit skipped threading._shutdown
import subprocess
p = subprocess.Popen([sys.executable, "-c", """if 1:
import threading
from time import sleep
def child():
sleep(1)
# As a non-daemon thread we SHOULD wake up and nothing
# should be torn down yet
print "Woke up, sleep function is:", sleep
threading.Thread(target=child).start()
raise SystemExit
"""],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
self.assertEqual(stdout, "Woke up, sleep function is: <built-in function sleep>\n")
self.assertEqual(stderr, "")
def test_enumerate_after_join(self): def test_enumerate_after_join(self):
# Try hard to trigger #1703448: a thread is still returned in # Try hard to trigger #1703448: a thread is still returned in

View File

@ -540,6 +540,7 @@ Kevin O'Connor
Tim O'Malley Tim O'Malley
Pascal Oberndoerfer Pascal Oberndoerfer
Jeffrey Ollie Jeffrey Ollie
Adam Olsen
Grant Olson Grant Olson
Piet van Oostrum Piet van Oostrum
Jason Orendorff Jason Orendorff

View File

@ -12,6 +12,10 @@ What's New in Python 2.7 alpha 1
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #1722344: threading._shutdown() is now called in Py_Finalize(), which
fixes the problem of some exceptions being thrown at shutdown when the
interpreter is killed. Patch by Adam Olsen.
- Issue #7168: Document PyFloat_AsString and PyFloat_AsReprString, and - Issue #7168: Document PyFloat_AsString and PyFloat_AsReprString, and
note that they are unsafe and deprecated. note that they are unsafe and deprecated.

View File

@ -222,33 +222,6 @@ static int RunMainFromImporter(char *filename)
} }
/* Wait until threading._shutdown completes, provided
the threading module was imported in the first place.
The shutdown routine will wait until all non-daemon
"threading" threads have completed. */
#include "abstract.h"
static void
WaitForThreadShutdown(void)
{
#ifdef WITH_THREAD
PyObject *result;
PyThreadState *tstate = PyThreadState_GET();
PyObject *threading = PyMapping_GetItemString(tstate->interp->modules,
"threading");
if (threading == NULL) {
/* threading not imported */
PyErr_Clear();
return;
}
result = PyObject_CallMethod(threading, "_shutdown", "");
if (result == NULL)
PyErr_WriteUnraisable(threading);
else
Py_DECREF(result);
Py_DECREF(threading);
#endif
}
/* Main program */ /* Main program */
int int
@ -624,8 +597,6 @@ Py_Main(int argc, char **argv)
sts = PyRun_AnyFileFlags(stdin, "<stdin>", &cf) != 0; sts = PyRun_AnyFileFlags(stdin, "<stdin>", &cf) != 0;
} }
WaitForThreadShutdown();
Py_Finalize(); Py_Finalize();
#ifdef RISCOS #ifdef RISCOS
if (Py_RISCOSWimpFlag) if (Py_RISCOSWimpFlag)

View File

@ -17,6 +17,7 @@
#include "ast.h" #include "ast.h"
#include "eval.h" #include "eval.h"
#include "marshal.h" #include "marshal.h"
#include "abstract.h"
#ifdef HAVE_SIGNAL_H #ifdef HAVE_SIGNAL_H
#include <signal.h> #include <signal.h>
@ -61,6 +62,7 @@ static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *,
PyCompilerFlags *); PyCompilerFlags *);
static void err_input(perrdetail *); static void err_input(perrdetail *);
static void initsigs(void); static void initsigs(void);
static void wait_for_thread_shutdown(void);
static void call_sys_exitfunc(void); static void call_sys_exitfunc(void);
static void call_ll_exitfuncs(void); static void call_ll_exitfuncs(void);
extern void _PyUnicode_Init(void); extern void _PyUnicode_Init(void);
@ -390,6 +392,8 @@ Py_Finalize(void)
if (!initialized) if (!initialized)
return; return;
wait_for_thread_shutdown();
/* The interpreter is still entirely intact at this point, and the /* The interpreter is still entirely intact at this point, and the
* exit funcs may be relying on that. In particular, if some thread * 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 * or exit func is still waiting to do an import, the import machinery
@ -1666,6 +1670,32 @@ Py_FatalError(const char *msg)
#include "pythread.h" #include "pythread.h"
#endif #endif
/* Wait until threading._shutdown completes, provided
the threading module was imported in the first place.
The shutdown routine will wait until all non-daemon
"threading" threads have completed. */
static void
wait_for_thread_shutdown(void)
{
#ifdef WITH_THREAD
PyObject *result;
PyThreadState *tstate = PyThreadState_GET();
PyObject *threading = PyMapping_GetItemString(tstate->interp->modules,
"threading");
if (threading == NULL) {
/* threading not imported */
PyErr_Clear();
return;
}
result = PyObject_CallMethod(threading, "_shutdown", "");
if (result == NULL)
PyErr_WriteUnraisable(threading);
else
Py_DECREF(result);
Py_DECREF(threading);
#endif
}
#define NEXITFUNCS 32 #define NEXITFUNCS 32
static void (*exitfuncs[NEXITFUNCS])(void); static void (*exitfuncs[NEXITFUNCS])(void);
static int nexitfuncs = 0; static int nexitfuncs = 0;