Symptom
Intermittent failure in the linux verify CI job:
thread 'a_second_operation_is_refused_while_one_is_in_flight' panicked at crates/fprintd/tests/dbus_client_isolation.rs:174:
assertion `left == right` failed: one operation in flight per device
left: None
right: Some("net.reactivated.Fprint.Error.AlreadyInUse")
Passed on most runs (e.g. the #18/#20 merges), failed on the c43350a (#21) merge. So ~intermittent, not a code regression from any specific change.
Root cause
The daemon guard is correct: Device::start_active (crates/fprintd/src/device.rs) refuses a second operation only while the first is still running (!op.finished()). A completed pump is cleared.
The test races that window. The virtual device's enroll (fprint-backend-native, device.rs::enroll) runs enroll_stages iterations of yield_now().await with no blocking, so it completes in microseconds. By the time the test issues the second enroll_start, the first enroll has often already finished, the guard has cleared, and the second call succeeds (None) instead of returning AlreadyInUse.
So it is a timing race in the test's observation window, not a daemon bug.
Why not just retry
.config/nextest.toml is explicit: retries = 0 — "a nondeterministic one is a bug to fix, not to retry away." A deterministic fix is required.
Proposed deterministic fix
Give the virtual device a way to hold an operation genuinely in-flight until the test releases it:
- Add a runtime-agnostic gate (e.g. a
futures_channel::oneshot) to VirtualDeviceBuilder/VirtualDevice; enroll awaits it before completing when set. fprint-backend-native is publish = false, so this test-support hook does not ship.
- Change
Harness::serve (crates/fprintd/tests/common) from backend: fn() -> VirtualBackend to impl Fn() -> VirtualBackend so a test can capture the gate handle (a bare fn coerces, so existing callers are unaffected).
- The test then:
enroll_start (blocks on the gate, genuinely in-flight) → assert the second enroll_start is AlreadyInUse → open the gate → enroll_stop.
Impact
Blocks ci-required intermittently, so it can stall auto-merge of unrelated PRs (surfaced while finishing the 0.1.0 release).
Symptom
Intermittent failure in the
linux verifyCI job:Passed on most runs (e.g. the #18/#20 merges), failed on the c43350a (#21) merge. So ~intermittent, not a code regression from any specific change.
Root cause
The daemon guard is correct:
Device::start_active(crates/fprintd/src/device.rs) refuses a second operation only while the first is still running (!op.finished()). A completed pump is cleared.The test races that window. The virtual device's enroll (fprint-backend-native,
device.rs::enroll) runsenroll_stagesiterations ofyield_now().awaitwith no blocking, so it completes in microseconds. By the time the test issues the secondenroll_start, the first enroll has often already finished, the guard has cleared, and the second call succeeds (None) instead of returningAlreadyInUse.So it is a timing race in the test's observation window, not a daemon bug.
Why not just retry
.config/nextest.tomlis explicit:retries = 0— "a nondeterministic one is a bug to fix, not to retry away." A deterministic fix is required.Proposed deterministic fix
Give the virtual device a way to hold an operation genuinely in-flight until the test releases it:
futures_channel::oneshot) toVirtualDeviceBuilder/VirtualDevice;enrollawaits it before completing when set. fprint-backend-native ispublish = false, so this test-support hook does not ship.Harness::serve(crates/fprintd/tests/common) frombackend: fn() -> VirtualBackendtoimpl Fn() -> VirtualBackendso a test can capture the gate handle (a barefncoerces, so existing callers are unaffected).enroll_start(blocks on the gate, genuinely in-flight) → assert the secondenroll_startisAlreadyInUse→ open the gate →enroll_stop.Impact
Blocks
ci-requiredintermittently, so it can stall auto-merge of unrelated PRs (surfaced while finishing the 0.1.0 release).