Merged revisions 75570,75574,75624 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r75570 | antoine.pitrou | 2009-10-20 23:29:37 +0200 (mar., 20 oct. 2009) | 6 lines

  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.
........
  r75574 | antoine.pitrou | 2009-10-20 23:59:25 +0200 (mar., 20 oct. 2009) | 4 lines

  Test wouldn't work in debug mode.
  We probably need a function in test_support to handle this.
........
  r75624 | antoine.pitrou | 2009-10-23 14:01:13 +0200 (ven., 23 oct. 2009) | 3 lines

  Fix Windows buildbot failure
........
This commit is contained in:
Antoine Pitrou 2009-10-27 12:48:52 +00:00
parent f75774b542
commit 9aece75269
5 changed files with 71 additions and 29 deletions

View File

@ -284,6 +284,30 @@ class ThreadTests(unittest.TestCase):
self.failIf(rc == 2, "interpreted was blocked") self.failIf(rc == 2, "interpreted was blocked")
self.failUnless(rc == 0, "Unexpected error") self.failUnless(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.strip(),
"Woke up, sleep function is: <built-in function sleep>")
stderr = re.sub(r"^\[\d+ refs\]", "", stderr, re.MULTILINE).strip()
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

@ -517,6 +517,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

@ -4,6 +4,22 @@ Python News
(editors: check NEWS.help for information about editing NEWS using ReST.) (editors: check NEWS.help for information about editing NEWS using ReST.)
What's New in Python 2.6.5
==========================
*Release date: XX-XXX-20XX*
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.
Library
-------
What's New in Python 2.6.4 final? What's New in Python 2.6.4 final?
================================= =================================

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
@ -620,8 +593,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);
@ -387,6 +389,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
@ -1663,6 +1667,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;