Skip to content

Commit

Permalink
bpo-42308: Add threading.__excepthook__ (GH-23218)
Browse files Browse the repository at this point in the history
Add threading.__excepthook__ to allow retrieving the original value
of threading.excepthook in case it is set to a broken or a different
value.
  • Loading branch information
mariocj89 authored Nov 12, 2020
1 parent b5cc05b commit 750c5ab
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 0 deletions.
7 changes: 7 additions & 0 deletions Doc/library/threading.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ This module defines the following functions:

.. versionadded:: 3.8

.. data:: __excepthook__

Holds the original value of :func:`threading.excepthook`. It is saved so that the
original value can be restored in case they happen to get replaced with
broken or alternative objects.

.. versionadded:: 3.10

.. function:: get_ident()

Expand Down
5 changes: 5 additions & 0 deletions Doc/whatsnew/3.10.rst
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,11 @@ retrieve the functions set by :func:`threading.settrace` and
:func:`threading.setprofile` respectively.
(Contributed by Mario Corchero in :issue:`42251`.)

Add :data:`threading.__excepthook__` to allow retrieving the original value
of :func:`threading.excepthook` in case it is set to a broken or a different
value.
(Contributed by Mario Corchero in :issue:`42308`.)

traceback
---------

Expand Down
21 changes: 21 additions & 0 deletions Lib/test/test_threading.py
Original file line number Diff line number Diff line change
Expand Up @@ -1352,6 +1352,27 @@ def sys_hook(exc_type, exc_value, exc_traceback):
'Exception in threading.excepthook:\n')
self.assertEqual(err_str, 'threading_hook failed')

def test_original_excepthook(self):
def run_thread():
with support.captured_output("stderr") as output:
thread = ThreadRunFail(name="excepthook thread")
thread.start()
thread.join()
return output.getvalue()

def threading_hook(args):
print("Running a thread failed", file=sys.stderr)

default_output = run_thread()
with support.swap_attr(threading, 'excepthook', threading_hook):
custom_hook_output = run_thread()
threading.excepthook = threading.__excepthook__
recovered_output = run_thread()

self.assertEqual(default_output, recovered_output)
self.assertNotEqual(default_output, custom_hook_output)
self.assertEqual(custom_hook_output, "Running a thread failed\n")


class TimerTests(BaseTestCase):

Expand Down
4 changes: 4 additions & 0 deletions Lib/threading.py
Original file line number Diff line number Diff line change
Expand Up @@ -1200,6 +1200,10 @@ def excepthook(args, /):
stderr.flush()


# Original value of threading.excepthook
__excepthook__ = excepthook


def _make_invoke_excepthook():
# Create a local namespace to ensure that variables remain alive
# when _invoke_excepthook() is called, even if it is called late during
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Add :data:`threading.__excepthook__` to allow retrieving the original value
of :func:`threading.excepthook` in case it is set to a broken or a different
value. Patch by Mario Corchero.

0 comments on commit 750c5ab

Please sign in to comment.