Merged revisions 75571,75576-75577 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/branches/py3k

................
  r75571 | antoine.pitrou | 2009-10-20 23:52:47 +0200 (mar., 20 oct. 2009) | 11 lines

  Merged revisions 75570 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.
  ........
................
  r75576 | antoine.pitrou | 2009-10-21 00:02:29 +0200 (mer., 21 oct. 2009) | 10 lines

  Merged revisions 75574 via svnmerge from
  svn+ssh://pythondev@svn.python.org/python/trunk

  ........
    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.
  ........
................
  r75577 | antoine.pitrou | 2009-10-21 00:05:38 +0200 (mer., 21 oct. 2009) | 3 lines

  Another futile error in the previous commit :-(
................
This commit is contained in:
Antoine Pitrou 2009-10-20 22:08:36 +00:00
parent 2d4fce2dfb
commit cefb316e9e
5 changed files with 60 additions and 29 deletions

View file

@ -286,6 +286,29 @@ class ThreadTests(unittest.TestCase):
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, b"Woke up, sleep function is: <built-in function sleep>\n")
stderr = re.sub(br"^\[\d+ refs\]", b"", stderr, re.MULTILINE).strip()
self.assertEqual(stderr, b"")
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

@ -539,6 +539,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 3.1.2?
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 #7065: Fix a crash in bytes.maketrans and bytearray.maketrans when - Issue #7065: Fix a crash in bytes.maketrans and bytearray.maketrans when
using byte values greater than 127. Patch by Derk Drukker. using byte values greater than 127. Patch by Derk Drukker.

View file

@ -253,33 +253,6 @@ static int RunMainFromImporter(wchar_t *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
@ -647,8 +620,6 @@ Py_Main(int argc, wchar_t **argv)
sts = PyRun_AnyFileFlags(stdin, "<stdin>", &cf) != 0; sts = PyRun_AnyFileFlags(stdin, "<stdin>", &cf) != 0;
} }
WaitForThreadShutdown();
Py_Finalize(); Py_Finalize();
#ifdef __INSURE__ #ifdef __INSURE__

View file

@ -18,6 +18,7 @@
#include "eval.h" #include "eval.h"
#include "marshal.h" #include "marshal.h"
#include "osdefs.h" #include "osdefs.h"
#include "abstract.h"
#ifdef HAVE_SIGNAL_H #ifdef HAVE_SIGNAL_H
#include <signal.h> #include <signal.h>
@ -66,6 +67,7 @@ static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *,
static void err_input(perrdetail *); static void err_input(perrdetail *);
static void initsigs(void); static void initsigs(void);
static void call_py_exitfuncs(void); static void call_py_exitfuncs(void);
static void wait_for_thread_shutdown(void);
static void call_ll_exitfuncs(void); static void call_ll_exitfuncs(void);
extern void _PyUnicode_Init(void); extern void _PyUnicode_Init(void);
extern void _PyUnicode_Fini(void); extern void _PyUnicode_Fini(void);
@ -363,6 +365,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
@ -2059,6 +2063,34 @@ call_py_exitfuncs(void)
PyErr_Clear(); PyErr_Clear();
} }
/* 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;