From 2f170e961f080c395a8111a6c2da7a49123ff4de Mon Sep 17 00:00:00 2001 From: Mathieu Comandon Date: Mon, 15 Feb 2021 19:36:13 -0800 Subject: [PATCH] Fix process watcher --- share/lutris/bin/lutris-wrapper | 28 ++++++++++++++++++++++------ tests/test_lutris_wrapper.py | 17 +++++++++-------- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/share/lutris/bin/lutris-wrapper b/share/lutris/bin/lutris-wrapper index 6242a2cc0..c5d12ac23 100755 --- a/share/lutris/bin/lutris-wrapper +++ b/share/lutris/bin/lutris-wrapper @@ -117,7 +117,8 @@ def main(): signal.signal(signal.SIGTERM, hard_sig_handler) signal.signal(signal.SIGINT, hard_sig_handler) for child in watcher.iterate_children(): - kill_pid(child.pid) + kill_pid(child.pid, signum == signal.SIGKILL) + log("--terminated processes--") signal.signal(signal.SIGTERM, sig_handler) signal.signal(signal.SIGINT, sig_handler) @@ -159,21 +160,36 @@ def main(): log("Start monitoring process.") try: + # The initial wait loop: + # the initial process may have been excluded. Wait for the game + # to be considered "started". + if not watcher.is_alive(): + log("Waiting for game to start (first non-excluded process started)") + while not watcher.is_alive(): + reap_children() + time.sleep(0.1) + while watcher.is_alive(): reap_children() time.sleep(0.1) + + log("Monitored process exited.") reap_children() + # The game is no longer running. We kill other processes for child in watcher.iterate_children(): - kill_pid(child.pid) + kill_pid(child.pid, True) + reap_children() + log("All monitored processes have exited.") + except NoMoreChildren: log("All processes have quit") + if returncode is None: - log("Failed to read return code from process") - returncode = -1 - else: - log("Process exited with returncode %s" % returncode) + returncode = 0 + log("Monitored process didn't return an exit code.") + log("Exit with returncode %s" % returncode) sys.exit(returncode) diff --git a/tests/test_lutris_wrapper.py b/tests/test_lutris_wrapper.py index a14090cf3..97de2b408 100644 --- a/tests/test_lutris_wrapper.py +++ b/tests/test_lutris_wrapper.py @@ -36,6 +36,13 @@ class LutrisWrapperTestCase(unittest.TestCase): try: # Wait for the "Hello World" message that indicates that the process # tree has started. This message arrives on stdout. + for line in wrapper_proc.stdout: + if line.strip() == b'Hello World': + # We found the output we're looking for. + break + else: + self.fail("stdout EOF unexpectedly") + # Wait a short while to see if lutris-wrapper will exit (it shouldn't) try: wrapper_proc.wait(0.5) @@ -47,14 +54,8 @@ class LutrisWrapperTestCase(unittest.TestCase): self.fail("Process exited unexpectedly") finally: if wrapper_proc.returncode is None: - wrapper_proc.kill() - wrapper_proc.wait(3) - for line in wrapper_proc.stdout: - if line.strip() == b'Hello World': - # We found the output we're looking for. - break - else: - self.fail("stdout EOF unexpectedly") + wrapper_proc.terminate() + wrapper_proc.wait(30) wrapper_proc.stdout.close() def test_cleanup_children(self):