Don't start streams on exit

Rework the pause/resume loop to exit the loop
without starting the camera on exit
This commit is contained in:
Chris OBryan 2023-06-10 01:44:26 -05:00
parent 8cc28150d2
commit 0788a1a1a4

View File

@ -379,16 +379,26 @@ class CameraCapture(threading.Thread):
def capture_camera(name, config: CameraConfig, process_info): def capture_camera(name, config: CameraConfig, process_info):
stop_sigs = [signal.SIGTERM, signal.SIGINT] exit_sigs = [signal.SIGTERM, signal.SIGINT]
pause_sigs = [signal.SIGUSR2] pause_sigs = [signal.SIGUSR2]
resume_sigs = [signal.SIGUSR1] # add exit signals to resumes so that it wakes thread to exit if paused
resume_sigs = [signal.SIGUSR1] + exit_sigs
stop_sigs = pause_sigs + exit_sigs
exit_event = mp.Event()
stop_event = mp.Event() stop_event = mp.Event()
sig_queue: mp.Queue[signal.Signals] = mp.Queue() run_ffmpeg_event = mp.Event()
def receiveSignal(signalNumber, frame): def receiveSignal(signalNumber, frame):
logger.info(f"{name} Received signal {signalNumber}") if signalNumber in pause_sigs:
sig_queue.put(signalNumber) run_ffmpeg_event.clear()
if signalNumber in (stop_sigs + pause_sigs): elif signalNumber in resume_sigs:
run_ffmpeg_event.set()
if signalNumber in exit_sigs:
exit_event.set()
if signalNumber in stop_sigs:
stop_event.set() stop_event.set()
signal.signal(signal.SIGTERM, receiveSignal) signal.signal(signal.SIGTERM, receiveSignal)
@ -399,18 +409,13 @@ def capture_camera(name, config: CameraConfig, process_info):
setproctitle(f"frigate.capture:{name}") setproctitle(f"frigate.capture:{name}")
# Set initial paused or resumed state # Set initial paused or resumed state
init_sig = resume_sigs[0] if config.capture_enabled else pause_sigs[0] if config.capture_enabled:
run_ffmpeg_event.set()
def run_capture(): def run_capture():
frame_queue = process_info["frame_queue"] frame_queue = process_info["frame_queue"]
prev_sig = init_sig # Wait if paused and quit on exit event, otherwise run the camera
while prev_sig not in stop_sigs: while run_ffmpeg_event.wait() and not exit_event.is_set():
# Pause here until stopped or resumed
while not sig_queue.empty() or prev_sig not in resume_sigs:
# Abort on a STOP signal
if (prev_sig := sig_queue.get()) in stop_sigs:
break
logger.info(f"{name}: capture starting") logger.info(f"{name}: capture starting")
camera_watchdog = CameraWatchdog( camera_watchdog = CameraWatchdog(
name, name,
@ -422,14 +427,14 @@ def capture_camera(name, config: CameraConfig, process_info):
) )
camera_watchdog.start() camera_watchdog.start()
camera_watchdog.join() camera_watchdog.join()
stop_event.clear()
if sig_queue.empty(): if stop_event.is_set():
logger.warning(f"{name}: capture stopped without signal") stop_event.clear()
else:
logger.info(f"{name}: capture stopped") logger.info(f"{name}: capture stopped")
else:
logger.warning(f"{name}: capture stopped without signal")
# Run a background thread to prevent deadlock in signal handlers # Run a background thread to prevent deadlocks in signal handler
capture_thread = threading.Thread(target=run_capture) capture_thread = threading.Thread(target=run_capture)
capture_thread.start() capture_thread.start()
capture_thread.join() capture_thread.join()