Author vstinner
Recipients CyberJacob, Decorater, Matt Groth, ellisj, eric.araujo, lazka, mwh, ncoghlan, pitrou, tiagoaoa, tim.peters, undercoveridiot, vlasovskikh, vstinner
Date 2019-05-23.00:28:15
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1558571296.25.0.630742476366.issue1230540@roundup.psfhosted.org>
In-reply-to
Content
I wrote PR 13515 which adds threading.excepthook(). I chose to call threading.excepthook() even when run() raises SystemExit. In this case, threading.excepthook() simply does nothing. The idea is to really give the full control when threading.excepthook() is overriden. For example, log a warning when run() raises SystemExit. By the way, is it really a good idea to call sys.exit() from a thread? It sounds like a bug that should be reported, and not silently ignored, no?

Differences between sys.excepthook() and threading.excepthook():

* API: sys.excepthook(exctype, value, traceback, /) vs threading.excepthook(exc_type, exc_value, exc_tb, thread, /) -- addition thread parameter to display the name of the thread which raises an exception

* For SystemExit corner case, sys.excepthook() displays the exception, whereas threading.excepthook() silently ignores it

* When sys.stderr is None, sys.excepthook() does nothing, whereas threading.excepthook() tries harder: use its own copy of sys.stderr (saved when the thread has been created) from thread._stderr.

Thread._stderr was added by bpo-754449:

commit cc4e935ea593cede10cb1316e3faeabd708abca7
Author: Brett Cannon <bcannon@gmail.com>
Date:   Sat Jul 3 03:52:35 2004 +0000

    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).

Note: When sys.stderr is None, threading.excepthook() avoids the traceback module and renders the exception itself. Maybe threading.excepthook() should be reimplemented in C to make it even more reliable and more correct, especially during Python shutdown. Only daemon threads are impacted: Python finalization (Py_Finalize() C function) starts by calling threading._shutdown() which joins all non-daemon threads.


IMHO the threading.Thread semantics is too different than sys.excepthook() to reuse sys.excepthook() to handle threading.Thread.run() exception.

Another explanation is that sadly sys.excepthook() API uses exactly 3 positional-only arguments, and so the API cannot be easily extended to get a thread argument. When I designed sys.unraisablehook(), I chose to pass only one argument which has attributes, to prevent this issue.

I'm not comfortable to attempt to modify sys.excepthook() to make it behave differently if it's called from the main thread or from a different thread. It would have to call threading.current_thread().name to get the name of the current thread.


Let's say that in Python 3.8 threading.Thread now calls sys.execpthook() to handle uncaught run() exception. All applications which override sys.excepthook() on purpose will behave differently: start to log exceptions from threads. But existing code is unlikely to be prepared to implement black magic to check if we are a "thread" or the main thread, to decide if we should display a thread name, and also the "black magic" to get the current thread name.


One of my concern of reusing sys.excepthook to display threading exceptions is that adding more code to handle threads is a risk of raising a new exception while logging a threading exception :-(

IMHO threading.excepthook() is safer since it already has access to the thread.
History
Date User Action Args
2019-05-23 00:28:16vstinnersetrecipients: + vstinner, mwh, tim.peters, ncoghlan, ellisj, pitrou, tiagoaoa, eric.araujo, undercoveridiot, vlasovskikh, lazka, Decorater, CyberJacob, Matt Groth
2019-05-23 00:28:16vstinnersetmessageid: <1558571296.25.0.630742476366.issue1230540@roundup.psfhosted.org>
2019-05-23 00:28:16vstinnerlinkissue1230540 messages
2019-05-23 00:28:15vstinnercreate