(self, cause)
| 456 | or executor._shutdown_thread) |
| 457 | |
| 458 | def _terminate_broken(self, cause): |
| 459 | # Terminate the executor because it is in a broken state. The cause |
| 460 | # argument can be used to display more information on the error that |
| 461 | # lead the executor into becoming broken. |
| 462 | |
| 463 | # Mark the process pool broken so that submits fail right now. |
| 464 | executor = self.executor_reference() |
| 465 | if executor is not None: |
| 466 | executor._broken = ('A child process terminated ' |
| 467 | 'abruptly, the process pool is not ' |
| 468 | 'usable anymore') |
| 469 | executor._shutdown_thread = True |
| 470 | executor = None |
| 471 | |
| 472 | # All pending tasks are to be marked failed with the following |
| 473 | # BrokenProcessPool error |
| 474 | bpe = BrokenProcessPool("A process in the process pool was " |
| 475 | "terminated abruptly while the future was " |
| 476 | "running or pending.") |
| 477 | cause_str = None |
| 478 | if cause is not None: |
| 479 | cause_str = ''.join(cause) |
| 480 | else: |
| 481 | # No cause known, so report any processes that have |
| 482 | # terminated with nonzero exit codes, e.g. from a |
| 483 | # segfault. Multiple may terminate simultaneously, |
| 484 | # so include all of them in the traceback. |
| 485 | errors = [] |
| 486 | for p in self.processes.values(): |
| 487 | if p.exitcode is not None and p.exitcode != 0: |
| 488 | errors.append(f"Process {p.pid} terminated abruptly " |
| 489 | f"with exit code {p.exitcode}") |
| 490 | if errors: |
| 491 | cause_str = "\n".join(errors) |
| 492 | if cause_str: |
| 493 | bpe.__cause__ = _RemoteTraceback(f"\n'''\n{cause_str}'''") |
| 494 | |
| 495 | # Mark pending tasks as failed. |
| 496 | for work_id, work_item in self.pending_work_items.items(): |
| 497 | try: |
| 498 | work_item.future.set_exception(bpe) |
| 499 | except _base.InvalidStateError: |
| 500 | # set_exception() fails if the future is cancelled: ignore it. |
| 501 | # Trying to check if the future is cancelled before calling |
| 502 | # set_exception() would leave a race condition if the future is |
| 503 | # cancelled between the check and set_exception(). |
| 504 | pass |
| 505 | # Delete references to object. See issue16284 |
| 506 | del work_item |
| 507 | self.pending_work_items.clear() |
| 508 | |
| 509 | # Terminate remaining workers forcibly: the queues or their |
| 510 | # locks may be in a dirty state and block forever. |
| 511 | for p in self.processes.values(): |
| 512 | p.terminate() |
| 513 | |
| 514 | self.call_queue._terminate_broken() |
| 515 |
no test coverage detected