Found during a targeted code review, not from a user report:
- _run_jpeg_loop()/_run_h264_loop() operated directly on the shared
self._proc_jpeg/self._proc_h264 instance attributes in their cleanup,
unlike _run_mjpeg_loop() (already fixed for exactly this) which uses a
local `proc` reference. If a loop's task is cancelled - e.g. by
CameraCache.reset() after the printer rotates its stream URL on reboot -
while a new task has already started and assigned its own process to the
shared attribute, the cancelled task's cleanup killed the NEWER process
instead of its own, leaking its own ffmpeg child as an orphan. Applied
the same local-variable + identity-check pattern already used by
_run_mjpeg_loop.
- handle_api_settings_post and handle_api_update_apply were the only two
of ~84 handlers that called `await request.json()` without a try/except -
every other handler follows the established pattern of returning a clean
400 for a malformed body. A trivial malformed request to either endpoint
produced an unhandled 500 with a full traceback instead.
New tests in tests/test_camera_process_race.py,
tests/test_settings.py, and tests/test_update_check.py cover both.