Fix export deadlock by replacing preexec_fn with nice command (#22641)
Some checks are pending
CI / AMD64 Build (push) Waiting to run
CI / ARM Build (push) Waiting to run
CI / Jetson Jetpack 6 (push) Waiting to run
CI / AMD64 Extra Build (push) Blocked by required conditions
CI / ARM Extra Build (push) Blocked by required conditions
CI / Synaptics Build (push) Blocked by required conditions
CI / Assemble and push default build (push) Blocked by required conditions

subprocess.run() with preexec_fn forces Python to use fork() instead
of posix_spawn(). In Frigate's main process (75+ threads), fork()
creates a child that inherits locked mutexes from other threads. The
child may deadlocks e.g. on a pysqlite3 mutex before it can exec()
ffmpeg.

Replace preexec_fn=lower_priority (which calls os.nice(19)) with
prefixing the ffmpeg command with "nice -n 19", achieving the same
priority reduction without requiring preexec_fn. This allows Python
to use posix_spawn() which is safe in multithreaded processes.

Fixes both the primary export path and the CPU fallback retry path.
This commit is contained in:
Ivan Shvedunov 2026-03-26 15:34:28 +04:00 committed by GitHub
parent 0cf9d7d5b1
commit 909b40ba96
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -85,10 +85,6 @@ def validate_ffmpeg_args(args: str) -> tuple[bool, str]:
return True, ""
def lower_priority() -> None:
os.nice(PROCESS_PRIORITY_LOW)
class PlaybackSourceEnum(str, Enum):
recordings = "recordings"
preview = "preview"
@ -439,10 +435,9 @@ class RecordingExporter(threading.Thread):
return
p = sp.run(
ffmpeg_cmd,
["nice", "-n", str(PROCESS_PRIORITY_LOW)] + ffmpeg_cmd,
input="\n".join(playlist_lines),
encoding="ascii",
preexec_fn=lower_priority,
capture_output=True,
)
@ -467,10 +462,9 @@ class RecordingExporter(threading.Thread):
)
p = sp.run(
ffmpeg_cmd,
["nice", "-n", str(PROCESS_PRIORITY_LOW)] + ffmpeg_cmd,
input="\n".join(playlist_lines),
encoding="ascii",
preexec_fn=lower_priority,
capture_output=True,
)