Files
AuraVPN/crates
xah30 1f82bc41c0 feat(cli,aura-gui): v3.4.4 — graceful Shutdown via admin socket (#1)
Closes the long-standing "GUI Disconnect button doesn't actually kill aura"
bug. The previous kill path sent SIGTERM to sudo (our direct child) and
hoped sudo's signal forwarding would propagate to the aura child running
as root; in practice this is unreliable when the parent has no controlling
terminal (which Tauri-spawned children don't), so aura would survive the
"Disconnect" click with the TUN still up and the OS routes still installed.

## Implementation

Adds a `Shutdown` admin-socket request. The aura-cli main loops
(`client::run` and `server::run`) now `tokio::select!` between their normal
work (router.run() / accept loop) and a `tokio::sync::Notify` carried on
the shared `AdminState`. When an admin client posts `{"cmd":"shutdown"}`
the handler calls `state.shutdown.notify_one()`, the select! second arm
fires, the work future is dropped, `OsRouteGuard::Drop` rolls back the
installed system routes, and the process exits with `Ok(())` — clean exit
code 0, kernel reaps the TUN device, no orphan.

The whole round-trip is sub-500 ms in practice (the slow step is the
`route delete` invocations on macOS).

## What changed

* `aura-cli/src/admin.rs`: `Request::Shutdown` variant, `AdminState.shutdown:
  Arc<Notify>` field, handler that calls `notify_one()` + returns `Response::ok()`.
* `aura-cli/src/client.rs`: clones `admin_state.shutdown` before spawning the
  admin server task, then `tokio::select!`s between `router.run()` and
  `shutdown.notified()`. Whichever finishes first ends the function; OsRouteGuard
  Drop runs after.
* `aura-cli/src/server.rs`: same pattern around the `MultiServer::accept` loop —
  graceful exit on admin Shutdown leaves the accept loop, breaks, and the
  router_task is aborted on function return.
* `aura-cli/src/main.rs`: `aura shutdown --admin-socket <path>` subcommand for
  CLI control (also useful from launchd/systemd post-stop hooks).
* `aura-gui/src-tauri/src/admin.rs`: new `send_shutdown(path)` helper; factored
  out `round_trip()` for the common write-line + read-line pattern. Windows
  stub returns "not implemented".
* `aura-gui/src-tauri/src/cli_proc.rs`: `ClientHandle::kill` now tries admin
  Shutdown first (3 s poll for graceful exit), then SIGTERM to sudo (2 s),
  then SIGKILL as last resort. The admin path needs no sudo because the
  socket is already chmod 0666 from v3.4.1.

## Test

New `admin::tests::shutdown_request_fires_notify` unit test: spawns a
notified() waiter, calls `handle_request(Request::Shutdown)`, asserts the
waiter wakes within 200 ms. Combined with the existing 5 admin tests, all 6
pass.

`cargo test --workspace` — all green, `cargo clippy --workspace --all-targets
-- -D warnings` — clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 22:18:00 +03:00
..