diff --git a/CHANGELOG.md b/CHANGELOG.md index 697b7995c..1d09367f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to Bambuddy will be documented in this file. ## [0.2.2b2] - Unreleased +### Fixed +- **Windows: Server Shuts Down After 60 Seconds** ([#605](https://github.com/maziggy/bambuddy/issues/605)) — On Windows, terminating orphaned ffmpeg camera processes broadcast `CTRL_C_EVENT` to the entire process group, causing uvicorn to interpret it as a user-initiated shutdown. ffmpeg is now spawned in its own process group (`CREATE_NEW_PROCESS_GROUP`) so cleanup no longer affects the server. Reported by @Reactantvr. + ## [0.2.2b1] - 2026-03-03 ### Improved diff --git a/backend/app/api/routes/camera.py b/backend/app/api/routes/camera.py index 449add070..12c0f12ef 100644 --- a/backend/app/api/routes/camera.py +++ b/backend/app/api/routes/camera.py @@ -2,6 +2,8 @@ import asyncio import logging +import subprocess +import sys from collections.abc import AsyncGenerator from fastapi import APIRouter, Depends, HTTPException, Request @@ -223,10 +225,17 @@ async def generate_rtsp_mjpeg_stream( process = None try: + # On Windows, spawn ffmpeg in its own process group so that + # terminate() doesn't broadcast CTRL_C_EVENT to uvicorn (#605). + kwargs: dict = {} + if sys.platform == "win32": + kwargs["creationflags"] = subprocess.CREATE_NEW_PROCESS_GROUP + process = await asyncio.create_subprocess_exec( *cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, + **kwargs, ) # Track active process for cleanup