aboutsummaryrefslogtreecommitdiff
path: root/app/backends/servers.py
diff options
context:
space:
mode:
authorhistoria <historiavg@proton.me>2026-08-26 00:21:28 -0400
committerhistoria <historiavg@proton.me>2026-08-26 00:21:28 -0400
commit7cf7d2f7849936e3c84ee431433c2e8bcb6706ac (patch)
tree80d753cbd35929187ffc717a45f7bc3e9cbdbb1e /app/backends/servers.py
parent4c3e78c39c81d2997e88b84e1b5a25b244e870e4 (diff)
downloadtts-audiobook-generator-7cf7d2f7849936e3c84ee431433c2e8bcb6706ac.tar.gz
fix: harden server start/stop guards
Diffstat (limited to 'app/backends/servers.py')
-rw-r--r--app/backends/servers.py19
1 files changed, 18 insertions, 1 deletions
diff --git a/app/backends/servers.py b/app/backends/servers.py
index 965d7df..986d82a 100644
--- a/app/backends/servers.py
+++ b/app/backends/servers.py
@@ -27,6 +27,7 @@ import signal
import subprocess
import sys
import time
+from datetime import datetime
from pathlib import Path
from typing import Callable, List, Optional
@@ -253,6 +254,15 @@ def start(spec, progress: ProgressCallback = None,
return True
LOG_DIR.mkdir(parents=True, exist_ok=True)
+ # Refuse to double-start: a live pid file means a previous start is
+ # still booting (or its process is wedged). Spawning a second server
+ # on the same port would orphan the first with no pid record left.
+ if alive(spec.name):
+ report({"kind": "error",
+ "message": f"a {spec.name} server (pid "
+ f"{pid_for(spec.name)}) is already starting or "
+ "running; stop it first"})
+ return False
pid_file = _pid_path(spec.name)
if pid_file.exists():
try:
@@ -261,7 +271,10 @@ def start(spec, progress: ProgressCallback = None,
pass
cwd = getattr(spec, "cwd", None)
- log_handle = _log_path(spec.name).open("w", encoding="utf-8")
+ # Append so an earlier boot's output survives (crash-loop debugging);
+ # the child inherits the handle and the parent's copy is closed right
+ # after the spawn, so nothing leaks here.
+ log_handle = _log_path(spec.name).open("a", encoding="utf-8")
popen_kwargs = {"stdout": log_handle, "stderr": subprocess.STDOUT}
if cwd is not None:
popen_kwargs["cwd"] = str(cwd)
@@ -277,6 +290,10 @@ def start(spec, progress: ProgressCallback = None,
"message": f"could not start server: {exc}"})
log_handle.close()
return False
+ log_handle.write(f"\n=== boot {datetime.now():%Y-%m-%d %H:%M:%S} "
+ f"(pid {proc.pid}) ===\n")
+ log_handle.flush()
+ log_handle.close()
pid_file.write_text(str(proc.pid), encoding="utf-8")
report({"kind": "starting", "name": spec.name,