Issue #20526, #19466: Revert changes of issue #19466 which introduces a
authorVictor Stinner <victor.stinner@gmail.com>
Thu, 13 Feb 2014 11:48:54 +0000 (12:48 +0100)
committerVictor Stinner <victor.stinner@gmail.com>
Thu, 13 Feb 2014 11:48:54 +0000 (12:48 +0100)
regression: don't clear anymore the state of Python threads early during the
Python shutdown.

Lib/test/test_threading.py
Misc/NEWS
Python/pythonrun.c

index ad363582317f6b16bdc00fa1497a4a9b49013591..7170f60f1c0906bec3771eea5f70b38556f9d43e 100644 (file)
@@ -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()
 
index 1eb509ebc8aec8c7fd99b8948f1f569749514767..f44551a52cae6e115b126553f1ffe412665413db 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,10 @@ Release date: 2014-02-23
 Core and Builtins
 -----------------
 
+- Issue #20526: Revert changes of issue #19466 which introduces a regression:
+  don't clear anymore the state of Python threads early during the Python
+  shutdown.
+
 - Issue #20595: Make getargs.c C89 compliant.
 
 Library
index 34a291f353ef52a7f2ff69b5cbfad2111a351570..e9947e9ff68be0952c3f6010b7ea3c15033fe9b9 100644 (file)
@@ -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();