]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Improve exception handling for subprocess.run()
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 7 Dec 2023 11:48:53 +0000 (12:48 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 7 Dec 2023 17:56:00 +0000 (18:56 +0100)
Instead of having subprocess.run() kill child processes on exceptions
with SIGKILL, let's have it use SIGTERM instead. Because this is not
configurable, we have to override signal.SIGKILL with signal.SIGTERM
before we call subprocess.run().

mkosi/run.py

index f8501acf1def190c4a904055fcb32c680252e6a2..957b7c8049c030f4c0ae775940fbd8e9394a749c 100644 (file)
@@ -216,6 +216,18 @@ def fork_and_wait(target: Callable[[], None]) -> None:
     if rc != 0:
         raise subprocess.CalledProcessError(rc, ["self"])
 
+
+@contextlib.contextmanager
+def sigkill_to_sigterm() -> Iterator[None]:
+    old = signal.SIGKILL
+    signal.SIGKILL = signal.SIGTERM
+
+    try:
+        yield
+    finally:
+        signal.SIGKILL = old
+
+
 def run(
     cmdline: Sequence[PathString],
     check: bool = True,
@@ -259,20 +271,25 @@ def run(
         stdin = subprocess.DEVNULL
 
     try:
-        return subprocess.run(
-            cmdline,
-            check=check,
-            stdin=stdin,
-            stdout=stdout,
-            stderr=stderr,
-            input=input,
-            text=True,
-            user=user,
-            group=group,
-            env=env,
-            cwd=cwd,
-            preexec_fn=make_foreground_process,
-        )
+        # subprocess.run() will use SIGKILL to kill processes when an exception is raised.
+        # We'd prefer it to use SIGTERM instead but since this we can't configure which signal
+        # should be used, we override the constant in the signal module instead before we call
+        # subprocess.run().
+        with sigkill_to_sigterm():
+            return subprocess.run(
+                cmdline,
+                check=check,
+                stdin=stdin,
+                stdout=stdout,
+                stderr=stderr,
+                input=input,
+                text=True,
+                user=user,
+                group=group,
+                env=env,
+                cwd=cwd,
+                preexec_fn=make_foreground_process,
+            )
     except FileNotFoundError as e:
         die(f"{e.filename} not found.")
     except subprocess.CalledProcessError as e: