|
21 | 21 | from test import support |
22 | 22 |
|
23 | 23 |
|
| 24 | +# bpo-38203: Maximum delay in seconds to exit Python (call Py_Finalize()). |
| 25 | +# Used to protect against threading._shutdown() hang. |
| 26 | +# Must be smaller than buildbot "1200 seconds without output" limit. |
| 27 | +EXIT_TIMEOUT = 120.0 |
| 28 | + |
| 29 | + |
24 | 30 | class Regrtest: |
25 | 31 | """Execute a test suite. |
26 | 32 |
|
@@ -157,11 +163,6 @@ def display_progress(self, test_index, text): |
157 | 163 | def parse_args(self, kwargs): |
158 | 164 | ns = _parse_args(sys.argv[1:], **kwargs) |
159 | 165 |
|
160 | | - if ns.timeout and not hasattr(faulthandler, 'dump_traceback_later'): |
161 | | - print("Warning: The timeout option requires " |
162 | | - "faulthandler.dump_traceback_later", file=sys.stderr) |
163 | | - ns.timeout = None |
164 | | - |
165 | 166 | if ns.xmlpath: |
166 | 167 | support.junit_xml_list = self.testsuite_xml = [] |
167 | 168 |
|
@@ -611,16 +612,24 @@ def main(self, tests=None, **kwargs): |
611 | 612 |
|
612 | 613 | test_cwd = self.create_temp_dir() |
613 | 614 |
|
614 | | - # Run the tests in a context manager that temporarily changes the CWD |
615 | | - # to a temporary and writable directory. If it's not possible to |
616 | | - # create or change the CWD, the original CWD will be used. |
617 | | - # The original CWD is available from support.SAVEDCWD. |
618 | | - with support.temp_cwd(test_cwd, quiet=True): |
619 | | - # When using multiprocessing, worker processes will use test_cwd |
620 | | - # as their parent temporary directory. So when the main process |
621 | | - # exit, it removes also subdirectories of worker processes. |
622 | | - self.ns.tempdir = test_cwd |
623 | | - self._main(tests, kwargs) |
| 615 | + try: |
| 616 | + # Run the tests in a context manager that temporarily changes the CWD |
| 617 | + # to a temporary and writable directory. If it's not possible to |
| 618 | + # create or change the CWD, the original CWD will be used. |
| 619 | + # The original CWD is available from support.SAVEDCWD. |
| 620 | + with support.temp_cwd(test_cwd, quiet=True): |
| 621 | + # When using multiprocessing, worker processes will use test_cwd |
| 622 | + # as their parent temporary directory. So when the main process |
| 623 | + # exit, it removes also subdirectories of worker processes. |
| 624 | + self.ns.tempdir = test_cwd |
| 625 | + |
| 626 | + self._main(tests, kwargs) |
| 627 | + except SystemExit as exc: |
| 628 | + # bpo-38203: Python can hang at exit in Py_Finalize(), especially |
| 629 | + # on threading._shutdown() call: put a timeout |
| 630 | + faulthandler.dump_traceback_later(EXIT_TIMEOUT, exit=True) |
| 631 | + |
| 632 | + sys.exit(exc.code) |
624 | 633 |
|
625 | 634 | def getloadavg(self): |
626 | 635 | if self.win_load_tracker is not None: |
|
0 commit comments