bpo-1230540: Add threading.excepthook() by vstinner · Pull Request #13515 · python/cpython (original) (raw)

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Conversation37 Commits3 Checks0 Files changed

Conversation

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters

[ Show hidden characters]({{ revealButtonHref }})

vstinner

Add a new threading.excepthook() function which handles uncaught
Thread.run() exception. It can be overridden to control how uncaught
exceptions are handled.

threading.ExceptHookArgs is not documented on purpose: it should not
be used directly.

https://bugs.python.org/issue1230540

@vstinner

@vstinner

See PR #8610 for a different approach: reuse sys.excepthook.

@vstinner

In my current implementation, I chose to continue to rely on t_bootstrap() of Modules/_threadmodule.c to log exception in threading.excepthook().

Maybe another option would be to attempt to reuse sys.excepthook() to log threading.excepthook() new failure?

Maybe the best option would be to later reimplement threading.excepthook() in C which reduces a lot the risk of error during Python shutdown. In C, it's more reliable to call functions during Python shutdown. Especially functions which don't rely on Python modules, but only access the interpreter state, thread state and the current exception.

I prefer to start with a simple PR to introduce the new API, and later experiment the different options to make the code even more reliable.

graingert

@vstinner

@vstinner

Oops, I didn't revert properly my change which added "stderr" into arguments passed to threading.excepthook(). It's now fixed.

auvipy

@vstinner

@pitrou

From the doc: Handle uncaught :func:``Thread.run`` exception.

What if some C extension wants to report uncaught exceptions in C-created threads? Does it have to create a dummy Thread object?

For example, how about threads created by _thread.start_new_thread?

@vstinner

I modified my PR to use the threading identifier (threading.get_ident()) as the thread name if args.thread is None.

@vstinner

As you can see in test_excepthook_thread_None(), it's not possible to call directly threading.excepthook() directly only using the public API: threading._make_excepthook_args() is needed.

args = threading._make_excepthook_args([*sys.exc_info(), None])

Should it be made public? Maybe as threading.ExceptHookArgs?

Maybe it can be made public but not documented?

@vstinner

Add a new threading.excepthook() function which handles uncaught Thread.run() exception. It can be overridden to control how uncaught exceptions are handled.

threading.ExceptHookArgs is not documented on purpose: it should not be used directly.

@vstinner

I squashed my commits, rebased my PR on master and I renamed _make_excepthook_args as threading.ExceptHookArgs.

I chose to not document ExceptHookArgs. In the Python implementation, threading.ExceptHookArgs is a wrapper to threading._ExceptHookArgs: threading._ExceptHookArgs constructor takes N arguments, whereas ExceptHookArgs takes 1 argument.

Using threading.ExceptHookArgs, it's now possible to call directly threading.excepthook(threading.ExceptHook(...)) to log an error from a thread not created using threading.Thread, but using directly _thread.start_new_thread.

@pitrou: Does it look better to you?

@vstinner

I plan to merge this PR wednesday (in 2 days).

I don't see a strong opposition, and nobody came up with a working implementation for the idea of reusing sys.excepthook.

There is PR #8610 but I dislike it: threading.Thread doesn't call sys.excepthook to handle run() exception by default, it only calls sys.excepthook if it's overridden. Moreover, when sys.excepthook is called, the hook doesn't get access to the thread object :-(
https://bugs.python.org/issue1230540#msg343260

asvetlov

from traceback import print_exception as _print_exception
from collections import namedtuple
_ExceptHookArgs = namedtuple(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is namedtuple for possible future extending a list of provided arguments?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly. See sys.unraisablehook: I used the same approach and today I added a new "err_msg" attribute ;-)

@@ -953,10 +953,11 @@ print_exception_recursive(PyObject *f, PyObject *value, PyObject *seen)
}
void
PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb)
_PyErr_Display(PyObject *file, PyObject *exception, PyObject *value, PyObject *tb)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make it public maybe? PyErr_DisplayToFile or something like this?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to not add a new function to the public C API unless there is a clear need from users. In the past, the C API evolved organically and now it's a mess because nobody knows what is really used or not :-(

pitrou

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks mostly good to me. Some comments below.

@bedevere-bot

When you're done making the requested changes, leave the comment: I have made the requested changes; please review again.

@vstinner

@vstinner

@vstinner

I have made the requested changes; please review again.

@bedevere-bot

Thanks for making the requested changes!

@pitrou: please review the changes made to this pull request.

pitrou

@vstinner vstinner deleted the threading_excepthook branch

May 27, 2019 22:45

@vstinner

@vstinner

@lazka lazka mentioned this pull request

May 28, 2019

DinoV pushed a commit to DinoV/cpython that referenced this pull request

Jan 14, 2020

@vstinner @DinoV

Add a new threading.excepthook() function which handles uncaught Thread.run() exception. It can be overridden to control how uncaught exceptions are handled.

threading.ExceptHookArgs is not documented on purpose: it should not be used directly.

Reviewers

@asvetlov asvetlov asvetlov left review comments

@graingert graingert graingert left review comments

@pitrou pitrou pitrou approved these changes

@auvipy auvipy auvipy approved these changes

@serhiy-storchaka serhiy-storchaka Awaiting requested review from serhiy-storchaka