Fix preview worker pool leak: ffmpeg must not inherit worker stdin

The ffmpeg fallback in the preview worker inherited the worker's stdin
pipe (the framed request protocol). When a slow conversion was killed
at the 10s timeout, the orphaned ffmpeg grandchild kept that pipe open,
so the parent's proc.wait() blocked forever waiting for pipe EOF —
permanently sticking one dispatcher per event until the whole pool
starved and every preview request (pdf, image, office) returned 503.

- Run ffmpeg with stdin=DEVNULL (also stops it eating protocol bytes)
- Drop start_new_session (only needed for group kills, POSIX-only)
- Stop logging the master secret at worker startup
This commit is contained in:
2026-07-28 01:14:15 +00:00
parent 718d46e3f9
commit 1258eff42d
2 changed files with 16 additions and 7 deletions
+3 -1
View File
@@ -145,6 +145,9 @@ class _PreviewWorker:
async def kill(self) -> None:
if self.proc.returncode is None:
# Safe to hard-kill: the worker is stateless per request, and its
# subprocesses (ffmpeg) use stdin=DEVNULL so they never hold the
# worker's pipes open — proc.wait() cannot hang on pipe EOF.
with contextlib.suppress(ProcessLookupError):
self.proc.kill()
await self.proc.wait()
@@ -179,7 +182,6 @@ class _PreviewWorkerPool:
stdin=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
start_new_session=True,
)
_active_procs.add(proc)
try: