fix(core): always poll WireGuard stats regardless of Doze mode#1177
Merged
zaneschepke merged 1 commit intowgtunnel:masterfrom Mar 7, 2026
Merged
fix(core): always poll WireGuard stats regardless of Doze mode#1177zaneschepke merged 1 commit intowgtunnel:masterfrom
zaneschepke merged 1 commit intowgtunnel:masterfrom
Conversation
WireGuard statistics are read from the kernel (local memory, no network required), so skipping the poll during Doze mode was unnecessary and harmful: tunStateFlow would stop updating, preventing HandshakeRestartHandler from detecting a stale handshake during device sleep. The ping monitor retains the idle-mode check (pings need network access, which Android blocks during Doze). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Contributor
Author
28 tasks
Collaborator
|
Hello, The stats are not completely no cost and are only read from the kernel in kernel mode, not userspace (which most users are using). This does add a small overhead + jni for CPU in the background but it is a small amount and this probably causes more trouble than it is worth. I agree this should be changes so I'll merge this. Thanks! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
WireGuard statistics are read from the kernel (local memory, no network required), so skipping the poll during Doze mode was unnecessary and harmful: tunStateFlow would stop updating, preventing HandshakeRestartHandler from detecting a stale handshake during device sleep.
The ping monitor retains the idle-mode check (pings need network access, which Android blocks during Doze).
Problem
When Android enters Doze mode (screen off, device idle), the
startWgStatsPollloop inTunnelMonitoringHandlerwas skipping stat updates due to this guard:This caused
tunStateFlowto stop being updated, which in turn causedHandshakeRestartHandlerto stall — it monitorstunStateFlowto detect stale handshakes (no handshake in ~3.5 min). With no new stats flowing in, the handler could never observe the stale condition and never triggered a restart (#1176).The result: tunnels appeared Up in the UI but passed no traffic, and stayed frozen for the entire duration of Doze mode. Reported in #1036.
Why removing this check is safe
WireGuard tunnel statistics are read from kernel memory — specifically the WireGuard netlink interface. This is a local, synchronous operation that requires no network access. Doze mode restricts network I/O and wakelocks, but does not prevent reading kernel state. Polling stats every 1 second while idle is negligible CPU work and has no meaningful battery impact.
The ping loop correctly retains its
isDeviceIdleModecheck, since ICMP pings genuinely require network access that Doze blocks.Fix
Remove the idle guard from
startWgStatsPoll:tunStateFlownow stays current at all times.HandshakeRestartHandlercan detect a stale handshake within ~1 second even during Doze, and will trigger a tunnel restart. WireGuard handles the reconnection gracefully once network is available again.Testing