Skip to content

Commit 74ba4ce

Browse files
fix: kill all processes after timeout.
1 parent 9ec9cf7 commit 74ba4ce

File tree

1 file changed

+29
-14
lines changed

1 file changed

+29
-14
lines changed

apps/common/utils/tool_code.py

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import subprocess
99
import sys
1010
import signal
11+
import time
1112
import uuid_utils.compat as uuid
1213
from common.utils.logger import maxkb_logger
1314
from django.utils.translation import gettext_lazy as _
@@ -221,26 +222,40 @@ def get_tool_mcp_config(self, code, params):
221222
return tool_config
222223

223224
def _exec_sandbox(self, _code):
224-
kwargs = {'cwd': BASE_DIR}
225-
kwargs['env'] = {
225+
kwargs = {'cwd': BASE_DIR, 'env': {
226226
'LD_PRELOAD': self.sandbox_so_path,
227-
}
227+
}}
228228
maxkb_logger.debug(f"Sandbox execute code: {_code}")
229229
compressed_and_base64_encoded_code_str = base64.b64encode(gzip.compress(_code.encode())).decode()
230+
cmd = [
231+
'su', '-s', python_directory, '-c',
232+
f'import base64,gzip; exec(gzip.decompress(base64.b64decode(\'{compressed_and_base64_encoded_code_str}\')).decode())',
233+
self.user
234+
]
230235
try:
231-
subprocess_result = subprocess.run(
232-
['su', '-s', python_directory, '-c',
233-
f'import base64,gzip; exec(gzip.decompress(base64.b64decode(\'{compressed_and_base64_encoded_code_str}\')).decode())',
234-
self.user],
236+
proc = subprocess.Popen(
237+
cmd,
238+
stdout=subprocess.PIPE,
239+
stderr=subprocess.PIPE,
235240
text=True,
236-
capture_output=True,
237-
timeout=self.process_timeout_seconds,
238-
preexec_fn=os.setsid,
239-
**kwargs)
240-
except subprocess.TimeoutExpired as e:
241-
os.killpg(e.pid, signal.SIGKILL)
241+
**kwargs,
242+
start_new_session=True
243+
)
244+
proc.wait(timeout=self.process_timeout_seconds)
245+
return subprocess.CompletedProcess(
246+
proc.args,
247+
proc.returncode,
248+
proc.stdout.read(),
249+
proc.stderr.read()
250+
)
251+
except subprocess.TimeoutExpired:
252+
pgid = os.getpgid(proc.pid)
253+
os.killpg(pgid, signal.SIGTERM) #温和终止
254+
time.sleep(1) #留出短暂时间让进程清理
255+
if proc.poll() is None: #如果仍未终止,强制终止
256+
os.killpg(pgid, signal.SIGKILL)
257+
proc.wait()
242258
raise Exception(_("Sandbox process execution timeout, consider increasing MAXKB_SANDBOX_PYTHON_PROCESS_TIMEOUT_SECONDS."))
243-
return subprocess_result
244259

245260
def validate_mcp_transport(self, code_str):
246261
servers = json.loads(code_str)

0 commit comments

Comments
 (0)