Skip to content

Commit

Permalink
Wait on parent if poll() does not return an exit code
Browse files Browse the repository at this point in the history
This handles the shutdown race in FFPuppet.wait() as well.
  • Loading branch information
tysmith committed Sep 15, 2023
1 parent a58b202 commit b3e8cc9
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 2 deletions.
5 changes: 4 additions & 1 deletion src/ffpuppet/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -958,7 +958,10 @@ def wait(self, timeout: Optional[float] = None) -> bool:
True if processes exit before timeout expires otherwise False.
"""
assert timeout is None or timeout >= 0
if not wait_procs(list(self.get_processes()), timeout=timeout)[1]:
procs = list(self.get_processes())
if not procs and self._proc and self._proc.poll() is None:
procs = [Process(self._proc.pid)]
if not wait_procs(procs, timeout=timeout)[1]:
return True
LOG.debug("wait(timeout=%0.2f) timed out", timeout)
return False
9 changes: 8 additions & 1 deletion src/ffpuppet/test_ffpuppet.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,11 @@ def test_ffpuppet_06(mocker):
class StubbedProc(FFPuppet):
# pylint: disable=arguments-differ
def close(self, **_):
self._proc = None
self.reason = Reason.CLOSED

def launch(self):
self._proc = mocker.Mock(spec=Popen, pid=os.getpid())
self.reason = None

def get_pid(self):
Expand All @@ -206,9 +208,14 @@ def get_pid(self):

fake_wait_procs = mocker.patch("ffpuppet.core.wait_procs", autospec=True)
with StubbedProc() as ffp:
ffp.launch()
# process not running
fake_wait_procs.return_value = ([], [])
ffp.launch()
assert ffp.wait()
assert fake_wait_procs.call_count == 1
fake_wait_procs.reset_mock()
# process is shutting down
ffp._proc.poll.return_value = None
assert ffp.wait()
assert fake_wait_procs.call_count == 1
fake_wait_procs.reset_mock()
Expand Down

0 comments on commit b3e8cc9

Please sign in to comment.