-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathmanaged_subprocess_fix.patch
More file actions
82 lines (79 loc) · 5.19 KB
/
Copy pathmanaged_subprocess_fix.patch
File metadata and controls
82 lines (79 loc) · 5.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
From 68e2f03bdd8b98f7f4d760ee0f8f28db13c46e05 Mon Sep 17 00:00:00 2001
From: Your Name <tushar.18246@gmail.com>
Date: Tue, 2 Jun 2026 22:00:09 +0530
Subject: [PATCH] fix: add managed_subprocess with safe secondary timeout
handling during kill
---
subprocess_utils.py | 62 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 62 insertions(+)
create mode 100644 subprocess_utils.py
diff --git a/subprocess_utils.py b/subprocess_utils.py
new file mode 100644
index 0000000..aa3b991
--- /dev/null
+++ b/subprocess_utils.py
@@ -0,0 +1,62 @@
+"""
+Robust subprocess management with safe cleanup handling.
+Ensures process termination does not leave dangling resources.
+"""
+import subprocess
+import logging
+from typing import Optional
+
+logger = logging.getLogger(__name__)
+
+
+def managed_subprocess(
+ cmd: list,
+ timeout: float = 30.0,
+ kill_timeout: float = 2.0,
+ **kwargs,
+) -> subprocess.CompletedProcess:
+ """
+ Run a subprocess with guaranteed resource cleanup even if termination times out.
+
+ The second wait() after SIGKILL is wrapped so that a TimeoutExpired there
+ does not prevent stream handles from being closed.
+ """
+ kwargs.setdefault("capture_output", True)
+ kwargs.setdefault("text", True)
+ kwargs.setdefault("check", False)
+
+ proc: Optional[subprocess.Popen] = None
+ try:
+ proc = subprocess.Popen(cmd, **kwargs)
+ stdout, stderr = proc.communicate(timeout=timeout)
+ return subprocess.CompletedProcess(
+ args=cmd,
+ returncode=proc.returncode,
+ stdout=stdout,
+ stderr=stderr,
+ )
+ except subprocess.TimeoutExpired:
+ if proc is None:
+ raise
+ _force_kill(proc, kill_timeout)
+ stdout, stderr = proc.communicate()
+ return subprocess.CompletedProcess(
+ args=cmd,
+ returncode=proc.returncode if proc.returncode is not None else -1,
+ stdout=stdout or "",
+ stderr=stderr or "",
+ )
+
+
+def _force_kill(proc: subprocess.Popen, kill_timeout: float) -> None:
+ """Kill a subprocess and wait for it to exit. Handles secondary timeout."""
+ try:
+ proc.kill()
+ proc.wait(timeout=kill_timeout)
+ except subprocess.TimeoutExpired:
+ logger.warning(
+ "Subprocess did not exit within %.1fs after kill; continuing cleanup",
+ kill_timeout,
+ )
+ except Exception:
+ logger.exception("Unexpected error while killing subprocess")
--
2.51.1.windows.1