pyronear / pyronear/pyro-engine
Patrol thread can hang forever and freeze latest_image
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 19
- Forks
- 8
- PR merge metrics
- No merged PRs in 30d
Description
The camera API can serve frozen images for hours while everything looks healthy.
Seen on 2026-09-16 at chateau-eau-douadic (Pi 192.168.255.170, two Reolink cameras):
latest_imagereturned the exact same JPEG for all 8 camera/pose pairs over 12 minutes- camera 192.168.1.11 served a night IR frame at 12:05, while a live
captureon the same camera at the same second returned a sharp daylight image - the engine kept scoring those dead frames and logging
No wildfire, so the site was blind with no error anywhere
Cause
The patrol thread was alive but blocked in a PTZ call. In camera/adapters/reolink.py the 9 requests.post calls have no timeout, so move_camera, called by patrol_loop, can wait forever. The stop flag was set meanwhile and the frozen thread never saw it.
From there the API cannot recover:
start_patrolonly checksthread.is_alive(), so it answersalready_runningand never starts a new threadpatrol_statusalso checks the flag, so it answerspatrol_running: falselast_imagesis never updated again, andlatest_imagecarries no timestamp, so nobody can tell the frame is old- the stuck detector skips when the patrol is not running, which is exactly this case
What to change
- Add a default timeout to every request in the Reolink adapter, with one helper instead of 9 call sites.
- Share one "is patrol running" check, and let
start_patrolreplace a thread that is alive but has its flag set. - Store the capture time with each image in
last_images, expose it, and let the engine refuse a frame that is too old. - Do not disable the stuck detector when the patrol is not running.
- Engine side:
core.pystops the patrol only when it is already stopped (inverted condition), andis_dayis overwritten at each pose, so the last camera of the loop decides day or night for the whole site.
Workaround
Restart the camera API container. The engine starts a clean patrol on the next cycle.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with camera/adapters/reolink.py and trace move_camera through patrol_loop, then inspect the patrol state and image handling named in the issue. Read core.py for the inverted stop condition and is_day overwrite. Done means stalled requests recover, patrol status and replacement behave consistently, image age is exposed and enforced, the detector still checks stopped patrols, and day/night state is correct across poses.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend, embedded-iot
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100