Files
amethyst/tools
Claude db378a105c feat(tor): self-heal — drop & rebuild Arti on network change and stuck Connecting
When Arti's in-memory TorClient gets into a broken state (bad guards from a
previous network, dead circuits, expired consensus held in memory), nothing
short of a process restart used to recover it: the JNI exposed initialize /
startSocksProxy / stopSocksProxy but no way to drop the TorClient, and the
Kotlin side gated initialize behind a one-shot AtomicBoolean. force-stop
preserved the on-disk arti/state/, toggle-off-then-on only re-bound the SOCKS
listener on the same broken client, and wiping app data was the only way out.

Rust side
- New JNI Java_..._ArtiNative_destroy: aborts the SOCKS listener task, aborts
  all in-flight per-connection handlers (each holds an Arc<TorClient> clone
  that would otherwise pin the state file lock), waits 500ms, drops the static
  ARTI_CLIENT. Next initialize() call creates a fresh client and re-bootstraps.
- Track handler JoinHandles in HANDLER_TASKS so destroy can abort them; cull
  finished ones on each accept to keep the Vec bounded.

Kotlin side
- TorService.reset() / resetWithCleanState() — drop the native client, flip
  initialized=false. The second variant also wipes arti/state/ on disk to
  rebuild guard selection from scratch.
- TorManager.resetEpoch StateFlow is now part of the status combine; bumping
  it re-fires the INTERNAL branch which calls service.start() and runs full
  Arti re-init.
- onNetworkChange (wired from ConnectivityManager.networkId distinctUntilChanged)
  now calls service.reset() + clears the persisted bypass approval + bumps the
  epoch. Replaces the previous clearSessionBypass() which only touched the
  in-memory bypass half.
- Self-heal watchdog: when status sits at Connecting for >45s (before the 60s
  connectionFailure dialog), calls resetWithCleanState. Rate-limited to one
  per 5 minutes so a permanently broken network doesn't loop us. onNetworkChange
  primes lastSelfHealAtMs so a slow legitimate post-network-change bootstrap
  doesn't get a second reset on top of itself.

Rebuilds: libarti_android.so for arm64-v8a + x86_64 (NDK 27, 16KB-page aligned).
2026-05-26 19:09:54 +00:00
..