mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-08-03 09:38:15 +03:00
Added stop_event to util.Process (#14142)
* Added stop_event to util.Process util.Process will take care of receiving signals when the stop_event is accessed in the subclass. If it never is, SystemExit is raised instead. This has the effect of still behaving like multiprocessing.Process when stop_event is not accessed, while still allowing subclasses to not deal with the hassle of setting it up. * Give each util.Process their own logger This will help to reduce boilerplate in subclasses. * Give explicit types to util.Process.__init__ This gives better type hinting in the editor. * Use util.Process facilities in AudioProcessor Boilerplate begone! * Removed pointless check in util.Process The log_listener.queue should never be None, unless something has gone extremely wrong in the log setup code. If we're that far gone, crashing is better. * Make sure faulthandler is enabled in all processes This has no effect currently since we're using the fork start_method. However, when we inevidably switch to forkserver (either by choice, or by upgrading to python 3.14+) not having this makes for some really fun failure modes :D
This commit is contained in:
+22
-28
@@ -2,8 +2,6 @@
|
||||
|
||||
import datetime
|
||||
import logging
|
||||
import signal
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
from typing import Tuple
|
||||
@@ -73,46 +71,42 @@ class AudioProcessor(util.Process):
|
||||
):
|
||||
super().__init__(name="frigate.audio_manager", daemon=True)
|
||||
|
||||
self.logger = logging.getLogger(self.name)
|
||||
self.camera_metrics = camera_metrics
|
||||
self.cameras = cameras
|
||||
|
||||
def run(self) -> None:
|
||||
stop_event = threading.Event()
|
||||
audio_threads: list[AudioEventMaintainer] = []
|
||||
|
||||
threading.current_thread().name = "process:audio_manager"
|
||||
signal.signal(signal.SIGTERM, lambda sig, frame: sys.exit())
|
||||
|
||||
if len(self.cameras) == 0:
|
||||
return
|
||||
|
||||
try:
|
||||
for camera in self.cameras:
|
||||
audio_thread = AudioEventMaintainer(
|
||||
camera,
|
||||
self.camera_metrics,
|
||||
stop_event,
|
||||
)
|
||||
audio_threads.append(audio_thread)
|
||||
audio_thread.start()
|
||||
for camera in self.cameras:
|
||||
audio_thread = AudioEventMaintainer(
|
||||
camera,
|
||||
self.camera_metrics,
|
||||
self.stop_event,
|
||||
)
|
||||
audio_threads.append(audio_thread)
|
||||
audio_thread.start()
|
||||
|
||||
self.logger.info(f"Audio processor started (pid: {self.pid})")
|
||||
self.logger.info(f"Audio processor started (pid: {self.pid})")
|
||||
|
||||
while True:
|
||||
signal.pause()
|
||||
finally:
|
||||
stop_event.set()
|
||||
for thread in audio_threads:
|
||||
thread.join(1)
|
||||
if thread.is_alive():
|
||||
self.logger.info(f"Waiting for thread {thread.name:s} to exit")
|
||||
thread.join(10)
|
||||
while not self.stop_event.wait():
|
||||
pass
|
||||
|
||||
for thread in audio_threads:
|
||||
if thread.is_alive():
|
||||
self.logger.warning(f"Thread {thread.name} is still alive")
|
||||
self.logger.info("Exiting audio processor")
|
||||
for thread in audio_threads:
|
||||
thread.join(1)
|
||||
if thread.is_alive():
|
||||
self.logger.info(f"Waiting for thread {thread.name:s} to exit")
|
||||
thread.join(10)
|
||||
|
||||
for thread in audio_threads:
|
||||
if thread.is_alive():
|
||||
self.logger.warning(f"Thread {thread.name} is still alive")
|
||||
|
||||
self.logger.info("Exiting audio processor")
|
||||
|
||||
|
||||
class AudioEventMaintainer(threading.Thread):
|
||||
|
||||
Reference in New Issue
Block a user