|
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