Skip to content

Commit d7e7d85

Browse files
[3.15] gh-151496: Use process groups in test_dtrace (GH-151512) (#151589)
gh-151496: Use process groups in test_dtrace (GH-151512) Create a new process group to run bpftrace commands, so it's possible to kill also child processes on timeout. (cherry picked from commit a064b32) Co-authored-by: Victor Stinner <vstinner@python.org>
1 parent a5c5edd commit d7e7d85

1 file changed

Lines changed: 23 additions & 5 deletions

File tree

Lib/test/test_dtrace.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import dis
22
import os.path
33
import re
4+
import signal
45
import subprocess
56
import sys
67
import sysconfig
@@ -50,6 +51,24 @@ def normalize_trace_output(output):
5051
)
5152

5253

54+
USE_PROCESS_GROUP = (hasattr(os, "setsid") and hasattr(os, "killpg"))
55+
56+
def create_process_group(*args, **kwargs):
57+
if USE_PROCESS_GROUP:
58+
kwargs['start_new_session'] = True
59+
return subprocess.Popen(*args, **kwargs)
60+
61+
def kill_process_group(proc):
62+
if USE_PROCESS_GROUP:
63+
try:
64+
os.killpg(proc.pid, signal.SIGKILL)
65+
except ProcessLookupError:
66+
pass
67+
else:
68+
proc.kill()
69+
proc.communicate() # Clean up
70+
71+
5372
class TraceBackend:
5473
EXTENSION = None
5574
COMMAND = None
@@ -205,15 +224,15 @@ def run_case(self, name, optimize_python=None):
205224
program = self.PROGRAMS[name].format(python=sys.executable)
206225

207226
try:
208-
proc = subprocess.Popen(
227+
proc = create_process_group(
209228
["bpftrace", "-e", program, "-c", " ".join(subcommand)],
210229
stdout=subprocess.PIPE,
211230
stderr=subprocess.PIPE,
212231
universal_newlines=True,
213232
)
214233
stdout, stderr = proc.communicate(timeout=60)
215234
except subprocess.TimeoutExpired:
216-
proc.kill()
235+
kill_process_group(proc)
217236
raise AssertionError("bpftrace timed out")
218237
except (FileNotFoundError, PermissionError) as e:
219238
raise unittest.SkipTest(f"bpftrace not available: {e}")
@@ -243,16 +262,15 @@ def assert_usable(self):
243262
# Check if bpftrace is available and can attach to USDT probes
244263
program = f'usdt:{sys.executable}:python:function__entry {{ printf("probe: success\\n"); exit(); }}'
245264
try:
246-
proc = subprocess.Popen(
265+
proc = create_process_group(
247266
["bpftrace", "-e", program, "-c", f"{sys.executable} -c pass"],
248267
stdout=subprocess.PIPE,
249268
stderr=subprocess.PIPE,
250269
universal_newlines=True,
251270
)
252271
stdout, stderr = proc.communicate(timeout=10)
253272
except subprocess.TimeoutExpired:
254-
proc.kill()
255-
proc.communicate() # Clean up
273+
kill_process_group(proc)
256274
raise unittest.SkipTest("bpftrace timed out during usability check")
257275
except OSError as e:
258276
raise unittest.SkipTest(f"bpftrace not available: {e}")

0 commit comments

Comments
 (0)