From e98cf131b7c82a834928dd7fa645b2e405a62765 Mon Sep 17 00:00:00 2001 From: Zhaofeng Zhang <24791380+vcfgv@users.noreply.github.com> Date: Thu, 20 Nov 2025 14:17:48 +0800 Subject: [PATCH 1/4] fix: improve backend process handling in launch script --- python/scripts/launch.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/python/scripts/launch.py b/python/scripts/launch.py index 067c901c2..c0a02811e 100644 --- a/python/scripts/launch.py +++ b/python/scripts/launch.py @@ -4,6 +4,7 @@ """ import os +import shlex import subprocess from datetime import datetime from pathlib import Path @@ -139,7 +140,7 @@ def main(): os.makedirs(log_dir, exist_ok=True) print(f"Logs will be saved to {log_dir}/") - processes = [] + # processes = [] logfiles = [] print( @@ -153,12 +154,29 @@ def main(): logfile = open(logfile_path, "w") logfiles.append(logfile) process = subprocess.Popen( - BACKEND_COMMAND, shell=True, stdout=logfile, stderr=logfile + shlex.split(BACKEND_COMMAND), + shell=False, + stdout=logfile, + stderr=logfile, ) - processes.append(process) + # processes.append(process) + # for process in processes: + # process.wait() + print(f"Backend (and agents) started with PID: {process.pid}") - for process in processes: + try: process.wait() + except KeyboardInterrupt: + print("\nStopping backend...") + + process.terminate() + + try: + process.wait(timeout=5) + except subprocess.TimeoutExpired: + process.kill() + print("Backend forced killed.") + for logfile in logfiles: logfile.close() print(f"All agents finished. Check {log_dir}/ for output.") From 1a28fd5df3b638e09c5ea8e6c4ea643ab189d24a Mon Sep 17 00:00:00 2001 From: Zhaofeng Zhang <24791380+vcfgv@users.noreply.github.com> Date: Thu, 20 Nov 2025 14:17:48 +0800 Subject: [PATCH 2/4] fix: update backend command in launch script for correct working directory --- python/scripts/launch.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/python/scripts/launch.py b/python/scripts/launch.py index c0a02811e..c8285b299 100644 --- a/python/scripts/launch.py +++ b/python/scripts/launch.py @@ -93,9 +93,7 @@ MAP_NAME_COMMAND[STRATEGY_AGENT_NAME] = ( f"uv run --env-file {ENV_PATH_STR} -m valuecell.agents.strategy_agent" ) -BACKEND_COMMAND = ( - f"cd {PYTHON_DIR_STR} && uv run --env-file {ENV_PATH_STR} -m valuecell.server.main" -) +BACKEND_COMMAND = f"uv run --env-file {ENV_PATH_STR} -m valuecell.server.main" FRONTEND_URL = "http://localhost:1420" @@ -158,6 +156,7 @@ def main(): shell=False, stdout=logfile, stderr=logfile, + cwd=PYTHON_DIR_STR, ) # processes.append(process) # for process in processes: From 0c3f18ce1a089e69765304e03371525fa33dae04 Mon Sep 17 00:00:00 2001 From: Zhaofeng Zhang <24791380+vcfgv@users.noreply.github.com> Date: Thu, 20 Nov 2025 14:26:39 +0800 Subject: [PATCH 3/4] fix: improve backend process termination handling in launch script --- python/scripts/launch.py | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/python/scripts/launch.py b/python/scripts/launch.py index c8285b299..c9d4d564b 100644 --- a/python/scripts/launch.py +++ b/python/scripts/launch.py @@ -6,6 +6,7 @@ import os import shlex import subprocess +import signal from datetime import datetime from pathlib import Path from typing import Dict @@ -151,12 +152,16 @@ def main(): print(f"Frontend available at {FRONTEND_URL}") logfile = open(logfile_path, "w") logfiles.append(logfile) + # Start the backend in a new process group so we can terminate children. + # On Windows use CREATE_NEW_PROCESS_GROUP; on POSIX use start_new_session. process = subprocess.Popen( shlex.split(BACKEND_COMMAND), shell=False, stdout=logfile, stderr=logfile, cwd=PYTHON_DIR_STR, + creationflags=(subprocess.CREATE_NEW_PROCESS_GROUP if os.name == "nt" else 0), + start_new_session=(os.name == "posix"), ) # processes.append(process) # for process in processes: @@ -168,12 +173,39 @@ def main(): except KeyboardInterrupt: print("\nStopping backend...") - process.terminate() + # Attempt graceful termination of the whole process group. + try: + if os.name == "posix": + # send SIGTERM to the process group + os.killpg(process.pid, signal.SIGTERM) + else: + # Windows: try to send CTRL_BREAK to the process group + try: + process.send_signal(signal.CTRL_BREAK_EVENT) + except Exception: + process.terminate() + except Exception: + # Fallback to terminating the parent process + try: + process.terminate() + except Exception: + pass + # Wait briefly for graceful shutdown try: process.wait(timeout=5) except subprocess.TimeoutExpired: - process.kill() + # Force kill the whole group if still alive + try: + if os.name == "posix": + os.killpg(process.pid, signal.SIGKILL) + else: + process.kill() + except Exception: + try: + process.kill() + except Exception: + pass print("Backend forced killed.") for logfile in logfiles: From f07f4def994d2c27d27fad6d400fc80dc78f7ad9 Mon Sep 17 00:00:00 2001 From: Zhaofeng Zhang <24791380+vcfgv@users.noreply.github.com> Date: Thu, 20 Nov 2025 14:30:19 +0800 Subject: [PATCH 4/4] make format --- python/scripts/launch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/scripts/launch.py b/python/scripts/launch.py index c9d4d564b..cb8d921c4 100644 --- a/python/scripts/launch.py +++ b/python/scripts/launch.py @@ -5,8 +5,8 @@ import os import shlex -import subprocess import signal +import subprocess from datetime import datetime from pathlib import Path from typing import Dict