From e28dc13cd5d3c5b4a514bf95f16694173a6237ea Mon Sep 17 00:00:00 2001 From: "memosr.eth" <96793918+memosr@users.noreply.github.com> Date: Sun, 8 Mar 2026 22:38:02 +0300 Subject: [PATCH 1/2] fix: store and close log file handles in rl_training_tool --- tools/rl_training_tool.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/tools/rl_training_tool.py b/tools/rl_training_tool.py index 6ffa6e237..bf4c6ad64 100644 --- a/tools/rl_training_tool.py +++ b/tools/rl_training_tool.py @@ -323,7 +323,10 @@ async def _spawn_training_run(run_state: RunState, config_path: Path): # Step 1: Start the Atropos API server (run-api) print(f"[{run_id}] Starting Atropos API server (run-api)...") - api_log_file = open(api_log, "w") + # File must stay open while the subprocess runs; we store the handle + # on run_state so _stop_training_run() can close it when done. + api_log_file = open(api_log, "w") # closed by _stop_training_run + run_state.api_log_file = api_log_file run_state.api_process = subprocess.Popen( ["run-api"], stdout=api_log_file, @@ -344,7 +347,8 @@ async def _spawn_training_run(run_state: RunState, config_path: Path): # Step 2: Start the Tinker trainer print(f"[{run_id}] Starting Tinker trainer: launch_training.py --config {config_path}") - trainer_log_file = open(trainer_log, "w") + trainer_log_file = open(trainer_log, "w") # closed by _stop_training_run + run_state.trainer_log_file = trainer_log_file run_state.trainer_process = subprocess.Popen( [sys.executable, "launch_training.py", "--config", str(config_path)], stdout=trainer_log_file, @@ -384,7 +388,8 @@ async def _spawn_training_run(run_state: RunState, config_path: Path): print(f"[{run_id}] Starting environment: {env_info.file_path} serve") - env_log_file = open(env_log, "w") + env_log_file = open(env_log, "w") # closed by _stop_training_run + run_state.env_log_file = env_log_file run_state.env_process = subprocess.Popen( [sys.executable, str(env_info.file_path), "serve", "--config", str(config_path)], stdout=env_log_file, @@ -480,6 +485,16 @@ def _stop_training_run(run_state: RunState): if run_state.status == "running": run_state.status = "stopped" + # Close log file handles that were opened for subprocess stdout. + for attr in ("env_log_file", "trainer_log_file", "api_log_file"): + fh = getattr(run_state, attr, None) + if fh is not None: + try: + fh.close() + except Exception: + pass + setattr(run_state, attr, None) + # ============================================================================ # Environment Discovery Tools From 7891050e06b5e8f1df45636813cf350df3f874ce Mon Sep 17 00:00:00 2001 From: "memosr.eth" <96793918+memosr@users.noreply.github.com> Date: Sun, 8 Mar 2026 22:39:17 +0300 Subject: [PATCH 2/2] fix: use Path.read_text() instead of open() in browser_tool --- tools/browser_tool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/browser_tool.py b/tools/browser_tool.py index e1bd32239..5f2f0bf7a 100644 --- a/tools/browser_tool.py +++ b/tools/browser_tool.py @@ -1523,7 +1523,7 @@ def cleanup_browser(task_id: Optional[str] = None) -> None: pid_file = os.path.join(socket_dir, f"{session_name}.pid") if os.path.isfile(pid_file): try: - daemon_pid = int(open(pid_file).read().strip()) + daemon_pid = int(Path(pid_file).read_text().strip()) os.kill(daemon_pid, signal.SIGTERM) logger.debug("Killed daemon pid %s for %s", daemon_pid, session_name) except (ProcessLookupError, ValueError, PermissionError, OSError):