Skip to main content

Module lock_order

Module lock_order 

Source
Expand description

A declared lock hierarchy for [PlayerController], and a tripwire that enforces it.

The controller carries seventeen separate mutexes, reached from the MPV event loop, JNI callbacks, sleep/autoplay timers, the session poller and every IPC command. Nothing about that arrangement prevents two threads taking the same two locks in opposite orders, which deadlocks the player outright — and this subsystem has already produced one deadlock (a tokio MutexGuard held in a match scrutinee, which stalled the AdvanceToNext arm).

Today the code is disciplined: acquisitions are scoped, and previous() for instance explicitly drops the backend guard before touching the queue. But that holds by convention, and convention is not checked. LOCK_ORDER writes the convention down and every_overlapping_acquisition_respects_the_order fails the build when a change breaks it.

Ordering only matters where one guard is still held while another lock is taken. Acquiring two locks one after another, each released before the next, cannot deadlock — so the analysis looks for overlap, not for mere sequence.

TRACES: UR-005 | DR-052

Structs§

Overlap
One lock acquired while another is still held.

Constants§

LOCK_ORDER
The order in which PlayerController’s locks may be nested.

Functions§

overlapping_acquisitions
Find every place src takes a lock while holding another.
parse_acquisition 🔒
The first self.other.lock_safe() on line that is not held.
parse_binding 🔒
let [mut] name = self.field.lock_safe()(name, field).
rank
Rank of field in LOCK_ORDER, or None if it is not a declared lock.