|
5 | 5 | import functools |
6 | 6 | import sys |
7 | 7 | import threading |
8 | | -import time |
9 | 8 | import traceback |
10 | 9 | from typing import NamedTuple |
11 | 10 | from typing import TYPE_CHECKING |
|
25 | 24 | from exceptiongroup import ExceptionGroup |
26 | 25 |
|
27 | 26 |
|
28 | | -def join_threads() -> None: |
29 | | - start = time.monotonic() |
30 | | - current_thread = threading.current_thread() |
31 | | - # This function is executed right at the end of the pytest run, just |
32 | | - # before we return an exit code, which is where the interpreter joins |
33 | | - # any remaining non-daemonic threads anyway, so it's ok to join all the |
34 | | - # threads. However there might be threads that depend on some shutdown |
35 | | - # signal that happens after pytest finishes, so we want to limit the |
36 | | - # join time somewhat. A one second timeout seems reasonable. |
37 | | - timeout = 1 |
38 | | - for thread in threading.enumerate(): |
39 | | - if thread is not current_thread and not thread.daemon: |
40 | | - # TODO: raise an error/warning if there's dangling threads. |
41 | | - thread.join(timeout - (time.monotonic() - start)) |
42 | | - |
43 | | - |
44 | 27 | class ThreadExceptionMeta(NamedTuple): |
45 | 28 | msg: str |
46 | 29 | cause_msg: str |
@@ -96,7 +79,9 @@ def cleanup( |
96 | 79 | ) -> None: |
97 | 80 | try: |
98 | 81 | try: |
99 | | - join_threads() |
| 82 | + # We don't join threads here, so exceptions raised from any |
| 83 | + # threads still running by the time _threading_atexits joins them |
| 84 | + # do not get captured (see #13027). |
100 | 85 | collect_thread_exception(config) |
101 | 86 | finally: |
102 | 87 | threading.excepthook = prev_hook |
|
0 commit comments