[Python-checkins] cpython: Close #19466: Clear the frames of daemon threads earlier during the Python
victor.stinner
python-checkins at python.org
Tue Nov 12 16:45:42 CET 2013
http://hg.python.org/cpython/rev/c2a13acd5e2b
changeset: 87070:c2a13acd5e2b
user: Victor Stinner <victor.stinner at gmail.com>
date: Tue Nov 12 16:37:55 2013 +0100
summary:
Close #19466: Clear the frames of daemon threads earlier during the Python
shutdown to call objects destructors. So "unclosed file" resource warnings are
now corretly emitted for daemon threads.
files:
Lib/test/test_threading.py | 50 ++++++++++++++++++++++++++
Misc/NEWS | 4 ++
Python/pythonrun.c | 20 +++++++--
3 files changed, 69 insertions(+), 5 deletions(-)
diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py
--- a/Lib/test/test_threading.py
+++ b/Lib/test/test_threading.py
@@ -617,6 +617,52 @@
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 ")
+
+
class ThreadJoinOnShutdown(BaseTestCase):
def _run_and_join(self, script):
@@ -701,6 +747,10 @@
import sys
import time
import threading
+ import warnings
+
+ # ignore "unclosed file ..." warnings
+ warnings.filterwarnings('ignore', '', ResourceWarning)
thread_has_run = set()
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,10 @@
Core and Builtins
-----------------
+- Issue #19466: Clear the frames of daemon threads earlier during the
+ Python shutdown to call objects destructors. So "unclosed file" resource
+ warnings are now corretly emitted for daemon threads.
+
- Issue #19514: Deduplicate some _Py_IDENTIFIER declarations.
Patch by Andrei Dorian Duma.
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -576,11 +576,13 @@
_Py_Finalizing = tstate;
initialized = 0;
- /* Flush stdout+stderr */
- flush_std_files();
-
- /* Disable signal handling */
- PyOS_FiniInterrupts();
+ /* 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 immediatly). */
+ _PyThreadState_DeleteExcept(tstate);
/* Collect garbage. This may call finalizers; it's nice to call these
* before all modules are destroyed.
@@ -595,6 +597,7 @@
* 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
@@ -602,6 +605,13 @@
while (PyGC_Collect() > 0)
/* nothing */;
#endif
+
+ /* Flush stdout+stderr */
+ flush_std_files();
+
+ /* Disable signal handling */
+ PyOS_FiniInterrupts();
+
/* Destroy all modules */
PyImport_Cleanup();
--
Repository URL: http://hg.python.org/cpython
More information about the Python-checkins
mailing list