Skip to content

Commit 5977b9d

Browse files
committed
1 parent 8e9c7b1 commit 5977b9d

File tree

1 file changed

+29
-14
lines changed

1 file changed

+29
-14
lines changed
Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import multiprocessing
22
import subprocess # nosec B404
33
import sys
4+
import traceback
45
from io import StringIO
56

67

@@ -16,14 +17,12 @@ def __call__(self):
1617
sys.stdout = StringIO()
1718
sys.stderr = StringIO()
1819

19-
returncode = 0
2020
try:
2121
exec(self.python_code, {"__name__": "__main__"}) # nosec B102
22+
returncode = 0
2223
except SystemExit as e: # Handle sys.exit()
2324
returncode = e.code if isinstance(e.code, int) else 0
24-
except Exception: # Capture other exceptions
25-
import traceback
26-
25+
except BaseException:
2726
traceback.print_exc()
2827
returncode = 1
2928
finally:
@@ -32,38 +31,54 @@ def __call__(self):
3231
stderr = sys.stderr.getvalue()
3332
sys.stdout = old_stdout
3433
sys.stderr = old_stderr
35-
self.result_queue.put((returncode, stdout, stderr))
34+
try: # noqa: SIM105
35+
self.result_queue.put((returncode, stdout, stderr))
36+
except Exception: # nosec B110
37+
# If the queue is broken (e.g., parent gone), best effort logging
38+
pass
3639

3740

3841
def run_python_code_safely(python_code, *, timeout=None):
39-
"""Replacement for subprocess.run that forces 'spawn' context"""
42+
"""Run Python code in a spawned subprocess, capturing stdout/stderr/output."""
4043
ctx = multiprocessing.get_context("spawn")
41-
result_queue = ctx.Queue()
44+
result_queue = ctx.SimpleQueue()
4245
process = ctx.Process(target=Worker(python_code, result_queue))
4346
process.start()
4447

4548
try:
46-
# Wait with timeout support
4749
process.join(timeout)
4850
if process.is_alive():
4951
process.terminate()
5052
process.join()
51-
raise subprocess.TimeoutExpired([sys.executable, "-c", python_code], timeout)
53+
return subprocess.CompletedProcess(
54+
args=[sys.executable, "-c", python_code],
55+
returncode=-9,
56+
stdout="",
57+
stderr=f"Process timed out after {timeout} seconds and was terminated.",
58+
)
5259

53-
# Get results from queue
5460
if result_queue.empty():
5561
return subprocess.CompletedProcess(
56-
[sys.executable, "-c", python_code],
62+
args=[sys.executable, "-c", python_code],
5763
returncode=-999,
5864
stdout="",
59-
stderr="Process failed to return results",
65+
stderr="Process exited without returning results.",
6066
)
6167

6268
returncode, stdout, stderr = result_queue.get()
6369
return subprocess.CompletedProcess(
64-
[sys.executable, "-c", python_code], returncode=returncode, stdout=stdout, stderr=stderr
70+
args=[sys.executable, "-c", python_code],
71+
returncode=returncode,
72+
stdout=stdout,
73+
stderr=stderr,
6574
)
75+
6676
finally:
67-
# Cleanup if needed
77+
try:
78+
result_queue.close()
79+
result_queue.join_thread()
80+
except Exception: # nosec B110
81+
pass
6882
if process.is_alive():
6983
process.kill()
84+
process.join()

0 commit comments

Comments
 (0)