diff --git a/serve/server.py b/serve/server.py index 768f6bcc374..dd81ca7b346 100644 --- a/serve/server.py +++ b/serve/server.py @@ -1082,6 +1082,7 @@ def __init__(self, exe: str, args: list[str], cwd: str | None = None, log: str | if log: self.log.close() raise + proc = self.proc # this start's process: close() may clear self.proc meanwhile # the READY read has a timeout (#1317): the lines come from a thread, up to READY, so the rest of the stream # stays for _pump (one reader at a time) ready_q: queue.Queue = queue.Queue() @@ -1110,23 +1111,24 @@ def __init__(self, exe: str, args: list[str], cwd: str | None = None, log: str | break loading.set() if self.max_context <= 0: - if timed_out: # still loading, or hung: end it, so the turn is not held for good + if timed_out and proc is not None: # still loading, or hung: end it, so the turn is not held for good try: - self.proc.kill() + proc.kill() except OSError: pass try: # its pipes and our handle on its log (the log stays) - self.proc.wait(timeout=5) - self.proc.stdin.close() - self.proc.stdout.close() + if proc is not None: + proc.wait(timeout=5) + proc.stdin.close() + proc.stdout.close() if log: self.log.close() except (OSError, subprocess.TimeoutExpired): pass - if not timed_out and _attempt < START_RETRIES and \ - transient_start_failure(log, log_start, time.monotonic() - spawned_at, self.proc.returncode): + if not timed_out and proc is not None and _attempt < START_RETRIES and \ + transient_start_failure(log, log_start, time.monotonic() - spawned_at, proc.returncode): wait_s = 2.0 * (2 ** _attempt) # 2, 4, 8 s: the previous process's GPU queues go away - exit_words = engine_exit_words(self.proc.returncode) + exit_words = engine_exit_words(proc.returncode) if start_log_marks(log, log_start): # the runtime said so itself (hsa_exception ...) print(f"[strata] the engine stopped while the GPU runtime was starting (most often right after " f"another engine exited, whose GPU queues were still being released" @@ -1144,7 +1146,7 @@ def __init__(self, exe: str, args: list[str], cwd: str | None = None, log: str | "the engine exited before it was ready") # EngineDied, not bare RuntimeError: a request waiting on this load must end with a 503 # through the request path's handler - a RuntimeError there left the turn with no answer (#1527) - note = "" if timed_out else start_exit_note(self.proc.returncode, exe) + note = "" if timed_out else start_exit_note(proc.returncode if proc is not None else None, exe) tail = start_log_tail(log, log_start) lines = [x for x in tail.split("\n")[2:] if x.strip()] if tail and lines and all(x.strip().startswith("[strata]") for x in lines):