aboutsummaryrefslogtreecommitdiff
path: root/app/backends/servers.py
diff options
context:
space:
mode:
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,