From 563018b5e1ace8364600fe8f72fdb789c539a82b Mon Sep 17 00:00:00 2001
From: ValueOn AG
Date: Wed, 1 Apr 2026 22:16:08 +0200
Subject: [PATCH] fixed tool execute subprocess
---
.../services/serviceAgent/sandboxExecutor.py | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)
diff --git a/modules/serviceCenter/services/serviceAgent/sandboxExecutor.py b/modules/serviceCenter/services/serviceAgent/sandboxExecutor.py
index 1882d7eb..15362e65 100644
--- a/modules/serviceCenter/services/serviceAgent/sandboxExecutor.py
+++ b/modules/serviceCenter/services/serviceAgent/sandboxExecutor.py
@@ -3,7 +3,6 @@
"""Sandboxed code execution for the AI agent executeCode tool."""
import logging
-import signal
import sys
import io
import traceback
@@ -72,15 +71,12 @@ async def executePython(code: str) -> Dict[str, Any]:
sys.stdout = capturedOutput
sys.stderr = capturedOutput
- if sys.platform != "win32":
- signal.signal(signal.SIGALRM, lambda *_: (_ for _ in ()).throw(TimeoutError("Execution timed out")))
- signal.alarm(_MAX_EXECUTION_TIME_S)
+ # Do not use signal.SIGALRM here: _run executes inside a thread-pool worker
+ # (asyncio.run_in_executor). signal.signal only works on the main thread.
+ # Wall-clock limit is enforced by asyncio.wait_for around run_in_executor.
exec(compile(code, "", "exec"), restrictedGlobals)
- if sys.platform != "win32":
- signal.alarm(0)
-
output = capturedOutput.getvalue()
if len(output) > _MAX_OUTPUT_CHARS:
output = output[:_MAX_OUTPUT_CHARS] + f"\n... (truncated at {_MAX_OUTPUT_CHARS} chars)"
@@ -94,14 +90,12 @@ async def executePython(code: str) -> Dict[str, Any]:
finally:
sys.stdout = oldStdout
sys.stderr = oldStderr
- if sys.platform != "win32":
- signal.alarm(0)
loop = asyncio.get_event_loop()
try:
result = await asyncio.wait_for(
loop.run_in_executor(None, _run),
- timeout=_MAX_EXECUTION_TIME_S + 5,
+ timeout=float(_MAX_EXECUTION_TIME_S) + 5.0,
)
return result
except asyncio.TimeoutError: