[Python-checkins] cpython (3.4): Issue #22423: Unhandled exception in thread no longer causes unhandled

serhiy.storchaka python-checkins at python.org
Sun Sep 21 21:30:45 CEST 2014


https://hg.python.org/cpython/rev/176579df4edd
changeset: 92504:176579df4edd
branch: 3.4
parent: 92497:7af0315bdfe0
user: Serhiy Storchaka <storchaka at gmail.com>
date: Sun Sep 21 22:08:13 2014 +0300
summary:
 Issue #22423: Unhandled exception in thread no longer causes unhandled
AttributeError when sys.stderr is None.
files:
 Lib/test/test_threading.py | 85 +++++++++++++++++++++++++-
 Lib/threading.py | 16 ++--
 Misc/NEWS | 3 +
 3 files changed, 94 insertions(+), 10 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
@@ -4,7 +4,7 @@
 
 import test.support
 from test.support import verbose, strip_python_stderr, import_module, cpython_only
-from test.script_helper import assert_python_ok
+from test.script_helper import assert_python_ok, assert_python_failure
 
 import random
 import re
@@ -15,7 +15,6 @@
 import unittest
 import weakref
 import os
-from test.script_helper import assert_python_ok, assert_python_failure
 import subprocess
 
 from test import lock_tests
@@ -962,6 +961,88 @@
 self.assertEqual(p.returncode, 0, "Unexpected error: " + stderr.decode())
 self.assertEqual(data, expected_output)
 
+ def test_print_exception(self):
+ script = r"""if True:
+ import threading
+ import time
+
+ running = False
+ def run():
+ global running
+ running = True
+ while running:
+ time.sleep(0.01)
+ 1/0
+ t = threading.Thread(target=run)
+ t.start()
+ while not running:
+ time.sleep(0.01)
+ running = False
+ t.join()
+ """
+ rc, out, err = assert_python_ok("-c", script)
+ self.assertEqual(out, b'')
+ err = err.decode()
+ self.assertIn("Exception in thread", err)
+ self.assertIn("Traceback (most recent call last):", err)
+ self.assertIn("ZeroDivisionError", err)
+ self.assertNotIn("Unhandled exception", err)
+
+ def test_print_exception_stderr_is_none_1(self):
+ script = r"""if True:
+ import sys
+ import threading
+ import time
+
+ running = False
+ def run():
+ global running
+ running = True
+ while running:
+ time.sleep(0.01)
+ 1/0
+ t = threading.Thread(target=run)
+ t.start()
+ while not running:
+ time.sleep(0.01)
+ sys.stderr = None
+ running = False
+ t.join()
+ """
+ rc, out, err = assert_python_ok("-c", script)
+ self.assertEqual(out, b'')
+ err = err.decode()
+ self.assertIn("Exception in thread", err)
+ self.assertIn("Traceback (most recent call last):", err)
+ self.assertIn("ZeroDivisionError", err)
+ self.assertNotIn("Unhandled exception", err)
+
+ def test_print_exception_stderr_is_none_2(self):
+ script = r"""if True:
+ import sys
+ import threading
+ import time
+
+ running = False
+ def run():
+ global running
+ running = True
+ while running:
+ time.sleep(0.01)
+ 1/0
+ sys.stderr = None
+ t = threading.Thread(target=run)
+ t.start()
+ while not running:
+ time.sleep(0.01)
+ running = False
+ t.join()
+ """
+ rc, out, err = assert_python_ok("-c", script)
+ self.assertEqual(out, b'')
+ self.assertNotIn("Unhandled exception", err.decode())
+
+
 class TimerTests(BaseTestCase):
 
 def setUp(self):
diff --git a/Lib/threading.py b/Lib/threading.py
--- a/Lib/threading.py
+++ b/Lib/threading.py
@@ -248,7 +248,7 @@
 
 def _is_owned(self):
 # Return True if lock is owned by current_thread.
- # This method is called only if __lock doesn't have _is_owned().
+ # This method is called only if _lock doesn't have _is_owned().
 if self._lock.acquire(0):
 self._lock.release()
 return False
@@ -749,12 +749,12 @@
 
 """
 
- __initialized = False
+ _initialized = False
 # Need to store a reference to sys.exc_info for printing
 # out exceptions when a thread tries to use a global var. during interp.
 # shutdown and thus raises an exception about trying to perform some
 # operation on/with a NoneType
- __exc_info = _sys.exc_info
+ _exc_info = _sys.exc_info
 # Keep sys.exc_clear too to clear the exception just before
 # allowing .join() to return.
 #XXX __exc_clear = _sys.exc_clear
@@ -926,10 +926,10 @@
 # shutdown) use self._stderr. Otherwise still use sys (as in
 # _sys) in case sys.stderr was redefined since the creation of
 # self.
- if _sys:
- _sys.stderr.write("Exception in thread %s:\n%s\n" %
- (self.name, _format_exc()))
- else:
+ if _sys and _sys.stderr is not None:
+ print("Exception in thread %s:\n%s" %
+ (self.name, _format_exc()), file=self._stderr)
+ elif self._stderr is not None:
 # Do the best job possible w/o a huge amt. of code to
 # approximate a traceback (code ideas from
 # Lib/traceback.py)
@@ -957,7 +957,7 @@
 # test_threading.test_no_refcycle_through_target when
 # the exception keeps the target alive past when we
 # assert that it's dead.
- #XXX self.__exc_clear()
+ #XXX self._exc_clear()
 pass
 finally:
 with _active_limbo_lock:
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -32,6 +32,9 @@
 Library
 -------
 
+- Issue #22423: Unhandled exception in thread no longer causes unhandled
+ AttributeError when sys.stderr is None.
+
 - Issue #21091: Fix API bug: email.message.EmailMessage.is_attachment is now
 a method. Since EmailMessage is provisional, we can change the API in a
 maintenance release, but we use a trick to remain backward compatible with
-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /