(self, start_time: float)
| 431 | f"{exc!r}") |
| 432 | |
| 433 | def wait_stopped(self, start_time: float) -> None: |
| 434 | # bpo-38207: RunWorkers.stop_workers() called self.stop() |
| 435 | # which killed the process. Sometimes, killing the process from the |
| 436 | # main thread does not interrupt popen.communicate() in |
| 437 | # WorkerThread thread. This loop with a timeout is a workaround |
| 438 | # for that. |
| 439 | # |
| 440 | # Moreover, if this method fails to join the thread, it is likely |
| 441 | # that Python will hang at exit while calling threading._shutdown() |
| 442 | # which tries again to join the blocked thread. Regrtest.main() |
| 443 | # uses EXIT_TIMEOUT to workaround this second bug. |
| 444 | while True: |
| 445 | # Write a message every second |
| 446 | self.join(1.0) |
| 447 | if not self.is_alive(): |
| 448 | break |
| 449 | dt = time.monotonic() - start_time |
| 450 | self.log(f"Waiting for {self} thread for {format_duration(dt)}") |
| 451 | if dt > WAIT_KILLED_TIMEOUT: |
| 452 | print_warning(f"Failed to join {self} in {format_duration(dt)}") |
| 453 | break |
| 454 | |
| 455 | |
| 456 | def get_running(workers: list[WorkerThread]) -> str | None: |
no test coverage detected