Skip to content

net/netmon: poll interfaces after wake#1

Open
eviaaaaa wants to merge 1 commit into
MetaCubeX:mainfrom
eviaaaaa:fix/metacubex-netmon-post-wake-polling
Open

net/netmon: poll interfaces after wake#1
eviaaaaa wants to merge 1 commit into
MetaCubeX:mainfrom
eviaaaaa:fix/metacubex-netmon-post-wake-polling

Conversation

@eviaaaaa

@eviaaaaa eviaaaaa commented Jul 19, 2026

Copy link
Copy Markdown

Mihomo's embedded tsnet.Server can remain offline after Windows wakes from
sleep. This was reproduced with:

  • Windows, WLAN, and Mihomo TUN
  • Mihomo 6414c563dda547f95195f12175a8e3d9f667984b
  • MetaCubeX Tailscale 1ab893d4162c4ef42fa39d6da63998edaab4f0e4

Stock Tailscale 1.98.2 did not reproduce the problem on the same machine, so
this report is limited to the Mihomo tsnet integration.

Reproduction

On wake, netmon took its first snapshot before WLAN and Mihomo TUN had
recovered:

old: Mihomo=up, WLAN=up, v4=true
new: Mihomo=down, WLAN=down, v4=false, v6=false
LinkChange: all links down
magicsock: SetNetworkUp(false)

WLAN connected about 476 ms later, and Mihomo started using it again after
about two seconds. Tailscale did not receive another interface event and
remained in network down.

At that point ordinary proxy traffic still returned HTTP 204, while the
Tailscale-routed request returned HTTP 502. A second sleep test produced 22
failed WireGuard handshakes over almost two minutes. Restarting the Mihomo core
restored the Tailscale route immediately.

Change

After a wake time jump, netmon now polls interfaces every 15 seconds for up to
10 minutes. The polls are non-forcing, so unchanged state does not result in a
callback or socket rebind. If WLAN recovers without another Windows event, a
later poll updates magicsock.networkUp.

The existing behavior on Android, iOS, and Plan 9 is unchanged because those
platforms do not run the wall-time wake monitor.

Validation

A patched Mihomo build was put through two sleep cycles without restarting the
core. The second cycle hit the original race and recovered on the first poll:

02:21:31.732  SetNetworkUp(false)
02:21:32.543  WLAN connected
02:21:33.811  Mihomo selected WLAN
02:21:47.380  SetNetworkUp(true)
02:21:47.558  DERP reconnected
02:21:50.641  WireGuard traffic resumed

Recovery took 15.6 seconds. A follow-up request was confirmed to use the
Tailscale outbound successfully.

Passed:

go test -count=1 ./net/netmon
go vet ./net/netmon
go test -count=1 ./wgengine ./tsnet
git diff --check origin/main...HEAD

Updates tailscale#10688

The first interface snapshot after a device wakes can run before Wi-Fi
or DHCP has recovered. Some operating systems then fail to deliver a
later address or route notification, leaving consumers with a stale
offline state.

After a detected time jump, poll interfaces every 15 seconds for 10
minutes. These non-forcing polls only notify callbacks when the
interface state changes.

Updates tailscale#10688

RELNOTE: Fixed devices sometimes remaining offline after waking from sleep.

Change-Id: Idbf9126f2aeb47db89c65dbcae5a27801834c7ec
Signed-off-by: evilhero <2278596667@qq.com>
@eviaaaaa
eviaaaaa marked this pull request as draft July 19, 2026 03:26
@eviaaaaa eviaaaaa closed this Jul 19, 2026
@eviaaaaa eviaaaaa reopened this Jul 19, 2026
@eviaaaaa
eviaaaaa marked this pull request as ready for review July 19, 2026 05:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant