server usb cycle update

This commit is contained in:
Brad Stein 2025-06-25 21:15:24 -05:00
parent c806faba6f
commit d4261c8383
2 changed files with 13 additions and 28 deletions

View File

@ -107,7 +107,8 @@ Restart=always
Environment=RUST_LOG=lesavka_server=debug,lesavka_server::usb_gadget=trace Environment=RUST_LOG=lesavka_server=debug,lesavka_server::usb_gadget=trace
Environment=RUST_BACKTRACE=1 Environment=RUST_BACKTRACE=1
Restart=always Restart=always
RestartSec=2 RestartSec=3
StandardError=append:/tmp/lesavka-server.log
StartLimitIntervalSec=30 StartLimitIntervalSec=30
StartLimitBurst=10 StartLimitBurst=10
User=root User=root

View File

@ -50,13 +50,9 @@ fn init_tracing() -> anyhow::Result<WorkerGuard> {
Ok(guard) Ok(guard)
} }
async fn open_with_retry( async fn open_with_retry(path: &str) -> anyhow::Result<tokio::fs::File> {
path: &str, const MAX_ATTEMPTS: usize = 40; // ≈ 2s (@50ms)
retries: usize, for attempt in 1..=MAX_ATTEMPTS {
base_delay_ms: u64,
) -> anyhow::Result<tokio::fs::File> {
let start = std::time::Instant::now();
for attempt in 0..=retries {
match OpenOptions::new() match OpenOptions::new()
.write(true) .write(true)
.custom_flags(libc::O_NONBLOCK) .custom_flags(libc::O_NONBLOCK)
@ -64,29 +60,17 @@ async fn open_with_retry(
.await .await
{ {
Ok(f) => { Ok(f) => {
info!("✅ opened {path} (attempt {attempt}, {} ms)", info!("✅ {path} opened on attempt #{attempt}");
start.elapsed().as_millis());
return Ok(f); return Ok(f);
} }
Err(e) if attempt < retries => { Err(e) if e.kind() == std::io::ErrorKind::Other /* EBUSY */ => {
let delay = base_delay_ms * 2u64.saturating_pow(attempt as u32); trace!("⏳ {path} busy, retry #{attempt}");
warn!( tokio::time::sleep(Duration::from_millis(50)).await;
"🕒 {path} busy: {e:?}; holders=[{}]; retry {attempt}/{retries} in {delay} ms",
owners_of(path)
);
tokio::time::sleep(Duration::from_millis(delay)).await;
} }
Err(e) => { Err(e) => return Err(e).with_context(|| format!("💥 opening {path}")),
error!(
"💥 all retries exhausted for {path} ({} ms): {e:?}; holders=[{}]",
start.elapsed().as_millis(),
owners_of(path)
);
return Err(e).with_context(|| format!("opening {path}"));
} }
} }
} Err(anyhow::anyhow!("💥 timeout waiting for {path} to become available"))
unreachable!()
} }
fn owners_of(path: &str) -> String { fn owners_of(path: &str) -> String {
@ -130,8 +114,8 @@ impl Handler {
tokio::time::sleep(Duration::from_millis(1000)).await; tokio::time::sleep(Duration::from_millis(1000)).await;
info!("🛠️ opening HID endpoints ..."); info!("🛠️ opening HID endpoints ...");
let kb = open_with_retry("/dev/hidg0", 20, 50).await?; let kb = open_with_retry("/dev/hidg0").await?;
let ms = open_with_retry("/dev/hidg1", 20, 50).await?; let ms = open_with_retry("/dev/hidg1").await?;
info!("✅ HID endpoints ready"); info!("✅ HID endpoints ready");
Ok(Self { Ok(Self {