Internal routine to wait for children that have exited.
(self, *, blocking=False)
| 561 | block_on_close = True |
| 562 | |
| 563 | def collect_children(self, *, blocking=False): |
| 564 | """Internal routine to wait for children that have exited.""" |
| 565 | if self.active_children is None: |
| 566 | return |
| 567 | |
| 568 | # If we're above the max number of children, wait and reap them until |
| 569 | # we go back below threshold. Note that we use waitpid(-1) below to be |
| 570 | # able to collect children in size(<defunct children>) syscalls instead |
| 571 | # of size(<children>): the downside is that this might reap children |
| 572 | # which we didn't spawn, which is why we only resort to this when we're |
| 573 | # above max_children. |
| 574 | while len(self.active_children) >= self.max_children: |
| 575 | try: |
| 576 | pid, _ = os.waitpid(-1, 0) |
| 577 | self.active_children.discard(pid) |
| 578 | except ChildProcessError: |
| 579 | # we don't have any children, we're done |
| 580 | self.active_children.clear() |
| 581 | except OSError: |
| 582 | break |
| 583 | |
| 584 | # Now reap all defunct children. |
| 585 | for pid in self.active_children.copy(): |
| 586 | try: |
| 587 | flags = 0 if blocking else os.WNOHANG |
| 588 | pid, _ = os.waitpid(pid, flags) |
| 589 | # if the child hasn't exited yet, pid will be 0 and ignored by |
| 590 | # discard() below |
| 591 | self.active_children.discard(pid) |
| 592 | except ChildProcessError: |
| 593 | # someone else reaped it |
| 594 | self.active_children.discard(pid) |
| 595 | except OSError: |
| 596 | pass |
| 597 | |
| 598 | def handle_timeout(self): |
| 599 | """Wait for zombies after self.timeout seconds of inactivity. |
no test coverage detected