fix(mesh): probe retries across the listener's port-hold windows

Linux double-opens ttys, so a probe racing the reconnect loop corrupted
both handshakes into silence (framework-pt, real Reticulum stick). Three
attempts 7s apart land in the listener's backoff gaps.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
archipelago 2026-07-22 17:48:04 -04:00
parent d86043193b
commit 5f01ec31ed

View File

@ -366,6 +366,25 @@ pub struct DeviceProbe {
/// loop can pick the device up afterwards. Reticulum uses the bare KISS
/// DETECT probe — no daemon spawn just to identify a stick.
pub(crate) async fn probe_device(path: &str) -> Result<DeviceProbe> {
// The listener's reconnect loop may hold this port for ~10s of every
// backoff cycle, and Linux happily double-opens a tty — two concurrent
// handshakes corrupt each other into silence (observed on framework-pt:
// every firmware "failed" while the listener was mid-cycle). Retry across
// the listener's idle gaps instead of failing on first collision.
let mut last_err = None;
for attempt in 0..3u32 {
if attempt > 0 {
tokio::time::sleep(Duration::from_secs(7)).await;
}
match probe_device_once(path).await {
Ok(p) => return Ok(p),
Err(e) => last_err = Some(e),
}
}
Err(last_err.unwrap_or_else(|| anyhow::anyhow!("probe failed")))
}
async fn probe_device_once(path: &str) -> Result<DeviceProbe> {
if super::super::reticulum::probe_rnode(path).await.is_ok() {
return Ok(DeviceProbe {
path: path.to_string(),