Graceful one-Ctrl-C shutdown with preview activity

- Preview workers ignore SIGINT (pool mode only) and load tracerite, so
  Ctrl-C no longer dumps a KeyboardInterrupt traceback per worker.
- Spawn workers in their own process group and kill with killpg, so a
  SIGKILLed worker cannot orphan an in-flight ffmpeg grandchild.
- Fail all pending and in-flight preview futures when the pool closes
  instead of orphaning them until timeout; never restart the pool once
  shut down (mid-shutdown requests get a quiet 'preview cancelled' 503).
- Re-raise CancelledError in the preview route instead of responding on
  a torn-down connection ('NoneType' is_closing crash).
- Log preview failures with logger.exception where they occur (in the
  worker, whose stderr is inherited) instead of re-logging a traceback-
  less error string in the parent.
This commit is contained in:
2026-08-11 21:32:16 +00:00
parent f3b3b5efd9
commit 07305538dc
2 changed files with 59 additions and 15 deletions
+7
View File
@@ -23,6 +23,7 @@ import os
os.environ.setdefault("SVT_LOG", "1")
import shlex
import signal
import struct
import subprocess
import sys
@@ -35,6 +36,7 @@ import msgspec
import numpy as np
import pymupdf
import pyvips
import tracerite
from blake3 import blake3
from cista import config
@@ -571,6 +573,8 @@ def _run_loop() -> None:
def main() -> None:
# Format tracebacks like the main process.
tracerite.load()
# Configure all log output to stderr before any imports that may emit
# logs. stderr is inherited by the parent, so this lands in the server
# log, formatted like the main process and tagged with the worker pid.
@@ -586,6 +590,9 @@ def main() -> None:
if len(sys.argv) > 1:
_run_once()
return
# Ctrl-C SIGINTs the whole process group; the parent pool terminates us
# (and our stdin EOF exits us) — don't dump KeyboardInterrupt tracebacks.
signal.signal(signal.SIGINT, signal.SIG_IGN)
# The command channel is a binary protocol on fd 1. Anything printed to
# stdout by Python code (e.g. a library emitting a warning via print())
# would corrupt the protocol, so redirect Python-level stdout to stderr