diff --git a/scripts/install-server.sh b/scripts/install-server.sh index d896513..5a72067 100755 --- a/scripts/install-server.sh +++ b/scripts/install-server.sh @@ -105,6 +105,11 @@ After=network.target lesavka-core.service ExecStart=/usr/local/bin/lesavka-server Restart=always Environment=RUST_LOG=lesavka_server=debug,lesavka_server::usb_gadget=trace +Environment=RUST_BACKTRACE=1 +Restart=always +RestartSec=2 +StartLimitIntervalSec=30 +StartLimitBurst=10 User=root [Install] diff --git a/server/src/main.rs b/server/src/main.rs index a761b8f..7b066ec 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -3,7 +3,7 @@ #![forbid(unsafe_code)] use std::sync::atomic::{AtomicBool, Ordering}; -use std::{pin::Pin, sync::Arc, time::Duration}; +use std::{panic, backtrace::Backtrace, pin::Pin, sync::Arc, time::Duration}; use futures_util::{Stream, StreamExt}; use tokio::{fs::{OpenOptions}, io::AsyncWriteExt, sync::Mutex}; use tokio_stream::{wrappers::ReceiverStream}; @@ -63,14 +63,17 @@ async fn open_with_retry( .await { Ok(f) => { - info!("✅ opened {path} on attempt #{attempt}"); + info!("✅ opened {path} ✅ after {attempt} attempt(s)"); return Ok(f); } Err(e) if attempt < retries => { - warn!("🕒 {path} not ready ({e}); retrying… #{attempt}"); // will retry + warn!("🕒 {path} not ready ({e:?}); retry {attempt}/{retries}"); tokio::time::sleep(Duration::from_millis(delay_ms)).await; } - Err(e) => return Err(e).with_context(|| format!("giving up on {path}")), + Err(e) => { + error!("💥 giving up on {path}: {e:?}"); + return Err(e).with_context(|| format!("opening {path}")); + } } } unreachable!() @@ -86,16 +89,20 @@ struct Handler { impl Handler { async fn make(gadget: UsbGadget) -> anyhow::Result { + info!("🛠️ Handler::make - cycling gadget ..."); gadget.cycle()?; - tokio::time::sleep(Duration::from_secs(1)).await; + tokio::time::sleep(Duration::from_millis(500)).await; - let kb = open_with_retry("/dev/hidg0", 10, 100).await?; - let ms = open_with_retry("/dev/hidg1", 10, 100).await?; + info!("🛠️ opening HID endpoints ..."); + let kb = open_with_retry("/dev/hidg0", 20, 50).await?; + let ms = open_with_retry("/dev/hidg1", 20, 50).await?; - Ok(Self { kb: Arc::new(Mutex::new(kb)), - ms: Arc::new(Mutex::new(ms)), - gadget, - did_cycle: AtomicBool::new(true), + info!("✅ HID endpoints ready"); + Ok(Self { + kb: Arc::new(Mutex::new(kb)), + ms: Arc::new(Mutex::new(ms)), + gadget, + did_cycle: AtomicBool::new(true), }) } } @@ -220,11 +227,22 @@ async fn main() -> anyhow::Result<()> { /* logging */ let _log_guard: WorkerGuard = init_tracing()?; + panic::set_hook(Box::new(|p| { + let bt = Backtrace::force_capture(); + error!("💥 panic: {p}\n{bt}"); + })); + /* auto‑cycle task */ // tokio::spawn(async { monitor_gc311_disconnect().await.ok(); }); let gadget = UsbGadget::new("lesavka"); - let handler = Handler::make(gadget.clone()).await?; + let handler = match Handler::make(gadget.clone()).await { + Ok(h) => h, + Err(e) => { + error!("💥 failed to create Handler: {e:#}"); + std::process::exit(1); + } + }; // tokio::spawn({ // let gadget = gadget.clone(); @@ -232,7 +250,7 @@ async fn main() -> anyhow::Result<()> { // loop { // tokio::time::sleep(Duration::from_secs(4)).await; // if LAST_HID_WRITE.elapsed().as_secs() > 3 { - // warn!("no HID traffic in 3 s – cycling UDC"); + // warn!("no HID traffic in 3 s - cycling UDC"); // let _ = gadget.cycle(); // } // }