summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorBrett Cannon <bcannon@gmail.com>2004-07-03 03:52:35 (GMT)
committerBrett Cannon <bcannon@gmail.com>2004-07-03 03:52:35 (GMT)
commitcc4e935ea593cede10cb1316e3faeabd708abca7 (patch)
tree20a9aaa0e9aff4daacc2b6ac350ccdc18a4700fc /Lib
parentf9bfdd850cd00e00c0895b3f73afd019b7a9dfdb (diff)
downloadcpython-cc4e935ea593cede10cb1316e3faeabd708abca7.zip
cpython-cc4e935ea593cede10cb1316e3faeabd708abca7.tar.gz
cpython-cc4e935ea593cede10cb1316e3faeabd708abca7.tar.bz2
threading.Thread objects will now print a traceback for an exception raised
during interpreter shutdown instead of masking it with another traceback about accessing a NoneType when trying to print the exception out in the first place. Closes bug #754449 (using patch #954922).
Diffstat (limited to 'Lib')
-rw-r--r--Lib/threading.py40
1 files changed, 38 insertions, 2 deletions
diff --git a/Lib/threading.py b/Lib/threading.py
index ec955c2..e70c61b 100644
--- a/Lib/threading.py
+++ b/Lib/threading.py
@@ -367,6 +367,11 @@ _limbo = {}
class Thread(_Verbose):
__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
def __init__(self, group=None, target=None, name=None,
args=(), kwargs={}, verbose=None):
@@ -381,6 +386,9 @@ class Thread(_Verbose):
self.__stopped = False
self.__block = Condition(Lock())
self.__initialized = True
+ # sys.stderr is not stored in the class like
+ # sys.exc_info since it can be changed between instances
+ self.__stderr = _sys.stderr
def _set_daemon(self):
# Overridden in _MainThread and _DummyThread
@@ -438,8 +446,36 @@ class Thread(_Verbose):
except:
if __debug__:
self._note("%s.__bootstrap(): unhandled exception", self)
- _sys.stderr.write("Exception in thread %s:\n%s\n" %
- (self.getName(), _format_exc()))
+ # If sys.stderr is no more (most likely from interpreter
+ # 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.getName(), _format_exc()))
+ else:
+ # Do the best job possible w/o a huge amt. of code to
+ # approximate a traceback (code ideas from
+ # Lib/traceback.py)
+ exc_type, exc_value, exc_tb = self.__exc_info()
+ try:
+ print>>self.__stderr, (
+ "Exception in thread " + self.getName() +
+ " (most likely raised during interpreter shutdown):")
+ print>>self.__stderr, (
+ "Traceback (most recent call last):")
+ while exc_tb:
+ print>>self.__stderr, (
+ ' File "%s", line %s, in %s' %
+ (exc_tb.tb_frame.f_code.co_filename,
+ exc_tb.tb_lineno,
+ exc_tb.tb_frame.f_code.co_name))
+ exc_tb = exc_tb.tb_next
+ print>>self.__stderr, ("%s: %s" % (exc_type, exc_value))
+ # Make sure that exc_tb gets deleted since it is a memory
+ # hog; deleting everything else is just for thoroughness
+ finally:
+ del exc_type, exc_value, exc_tb
else:
if __debug__:
self._note("%s.__bootstrap(): normal return", self)