Admin/dongle fix for the Rust backend (serverrs). Wire protocol, REST API and config format are unchanged.
Fix: rtl_tcp → local dongle switch returning a proxy 502
Saving a dongle that changes the source from a remote rtl_tcp feed to a local USB device returned 200, then the immediate /api/admin/dongles request could receive the reverse proxy's HTML 502 page. The server process stayed healthy and recovered by itself.
Cause: the background reinitialisation performed the blocking rtlsdr_open (USB enumeration/reset) directly on a tokio worker, and stopped the old source with an immediate task abort. On a small host (especially 1 vCPU) that could stall request handling for long enough for the proxy to return 502, and aborting a local source mid-read_sync could close the device under the read.
Changes:
- Local USB open now runs in
tokio::task::spawn_blocking, so HTTP/WebSocket workers stay responsive during dongle reinit. - Local USB device enumeration in the admin API is also off the async workers.
- Stopping a dongle now signals cancellation and waits up to 2 s for the source loop to finish before the device is closed, instead of aborting immediately.
- The admin UI retries the dongle list for up to ~1.8 s on transient 5xx/network failures after a reinit.
- Reinit success/failure is now logged.
Verified locally with a fake rtl_tcp feed: PUT returns 200, the immediate dongle-list GETs return 200 in under 1 ms, and the local device opens ~0.4 s later.
Tests
cargo test: 115/115. Client typecheck and production build are clean.
Docker
ghcr.io/gbozo/no-sdr:2.11.4-rust — multi-arch (linux/amd64 + linux/arm64), -rust suffix only.