diff -r 2ba583191550 Lib/test/test_threading.py --- a/Lib/test/test_threading.py Tue Feb 11 18:40:56 2014 +0100 +++ b/Lib/test/test_threading.py Wed Feb 12 10:52:06 2014 +0100 @@ -616,51 +616,6 @@ class ThreadTests(BaseTestCase): t.join() self.assertRaises(ValueError, bs.release) - def test_locals_at_exit(self): - # Issue #19466: thread locals must not be deleted before destructors - # are called - rc, out, err = assert_python_ok("-c", """if 1: - import threading - - class Atexit: - def __del__(self): - print("thread_dict.atexit = %r" % thread_dict.atexit) - - thread_dict = threading.local() - thread_dict.atexit = "atexit" - - atexit = Atexit() - """) - self.assertEqual(out.rstrip(), b"thread_dict.atexit = 'atexit'") - - def test_warnings_at_exit(self): - # Issue #19466: try to call most destructors at Python shutdown before - # destroying Python thread states - filename = __file__ - rc, out, err = assert_python_ok("-Wd", "-c", """if 1: - import time - import threading - - def open_sleep(): - # a warning will be emitted when the open file will be - # destroyed (without being explicitly closed) while the daemon - # thread is destroyed - fileobj = open(%a, 'rb') - start_event.set() - time.sleep(60.0) - - start_event = threading.Event() - - thread = threading.Thread(target=open_sleep) - thread.daemon = True - thread.start() - - # wait until the thread started - start_event.wait() - """ % filename) - self.assertRegex(err.rstrip(), - b"^sys:1: ResourceWarning: unclosed file ") - @cpython_only def test_frame_tstate_tracing(self): # Issue #14432: Crash when a generator is created in a C thread that is @@ -786,10 +741,6 @@ class ThreadJoinOnShutdown(BaseTestCase) import sys import time import threading - import warnings - - # ignore "unclosed file ..." warnings - warnings.filterwarnings('ignore', '', ResourceWarning) thread_has_run = set() diff -r 2ba583191550 Misc/NEWS --- a/Misc/NEWS Tue Feb 11 18:40:56 2014 +0100 +++ b/Misc/NEWS Wed Feb 12 10:52:06 2014 +0100 @@ -12,6 +12,11 @@ Core and Builtins - Issue #20595: Make getargs.c C89 compliant. +- Issue #20526: Revert changes of issue #19466 which introduces a regression, + don't clear anymore the state of Python threads earlier during the Python + shutdown. + + Library ------- diff -r 2ba583191550 Python/pythonrun.c --- a/Python/pythonrun.c Tue Feb 11 18:40:56 2014 +0100 +++ b/Python/pythonrun.c Wed Feb 12 10:52:06 2014 +0100 @@ -582,13 +582,11 @@ Py_Finalize(void) _Py_Finalizing = tstate; initialized = 0; - /* Destroy the state of all threads except of the current thread: in - practice, only daemon threads should still be alive. Clear frames of - other threads to call objects destructor. Destructors will be called in - the current Python thread. Since _Py_Finalizing has been set, no other - Python threads can lock the GIL at this point (if they try, they will - exit immediately). */ - _PyThreadState_DeleteExcept(tstate); + /* Flush stdout+stderr */ + flush_std_files(); + + /* Disable signal handling */ + PyOS_FiniInterrupts(); /* Collect garbage. This may call finalizers; it's nice to call these * before all modules are destroyed. @@ -603,7 +601,6 @@ Py_Finalize(void) * XXX I haven't seen a real-life report of either of these. */ PyGC_Collect(); - #ifdef COUNT_ALLOCS /* With COUNT_ALLOCS, it helps to run GC multiple times: each collection might release some types from the type @@ -611,13 +608,6 @@ Py_Finalize(void) while (PyGC_Collect() > 0) /* nothing */; #endif - - /* Flush stdout+stderr */ - flush_std_files(); - - /* Disable signal handling */ - PyOS_FiniInterrupts(); - /* Destroy all modules */ PyImport_Cleanup();