aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/snippets/termination_signal_for_tests.md6
-rw-r--r--mesonbuild/mtest.py27
2 files changed, 26 insertions, 7 deletions
diff --git a/docs/markdown/snippets/termination_signal_for_tests.md b/docs/markdown/snippets/termination_signal_for_tests.md
new file mode 100644
index 0000000..e99ea16
--- /dev/null
+++ b/docs/markdown/snippets/termination_signal_for_tests.md
@@ -0,0 +1,6 @@
+## Changed the signal used to terminate a test process (group)
+
+A test process (group) is now terminated via SIGTERM instead of SIGKILL
+allowing the signal to be handled. However, it is now the responsibility of
+the custom signal handler (if any) to ensure that any process spawned by the
+top-level test processes is correctly killed.
diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py
index 32b87c6..c35ab5a 100644
--- a/mesonbuild/mtest.py
+++ b/mesonbuild/mtest.py
@@ -578,14 +578,27 @@ class SingleTestRunner:
if is_windows():
subprocess.run(['taskkill', '/F', '/T', '/PID', str(p.pid)])
else:
+
+ def _send_signal_to_process_group(pgid : int, signum : int):
+ """ sends a signal to a process group """
+ try:
+ os.killpg(pgid, signum) # type: ignore
+ except ProcessLookupError:
+ # Sometimes (e.g. with Wine) this happens.
+ # There's nothing we can do (maybe the process
+ # already died) so carry on.
+ pass
+
+ # Send a termination signal to the process group that setsid()
+ # created - giving it a chance to perform any cleanup.
+ _send_signal_to_process_group(p.pid, signal.SIGTERM)
+
+ # Make sure the termination signal actually kills the process
+ # group, otherwise retry with a SIGKILL.
try:
- # Kill the process group that setsid() created.
- os.killpg(p.pid, signal.SIGKILL) # type: ignore
- except ProcessLookupError:
- # Sometimes (e.g. with Wine) this happens.
- # There's nothing we can do (maybe the process
- # already died) so carry on.
- pass
+ p.communicate(timeout=0.5)
+ except subprocess.TimeoutExpired:
+ _send_signal_to_process_group(p.pid, signal.SIGKILL)
try:
p.communicate(timeout=1)
except subprocess.TimeoutExpired: