wgengine/netstack: avoid returning from sender goroutines on error (#21332)

Returning from injectToHost and injectToWireGuard leaves the two
goroutines dead and the host without having a way to send traffic.

This is especially relevant for android where the tundev is torn down
and recreated for every call to updateTUN() from a route table change or
roaming between networks.

Fixes #21155

Signed-off-by: Claus Lensbøl <claus@tailscale.com>
This commit is contained in:
Claus Lensbøl authored and GitHub committed 2026-09-21 13:56:52 -04:00
1 parent bb94defdd0
commit 3f3e56f412
1 file changed
+20 -2
+20 -2
View File
@@ -1055,7 +1055,16 @@ func (ns *Impl) injectToWireGuard() {
}
if err := ns.tundev.InjectOutboundPacketBuffer(pkt); err != nil {
ns.logf("netstack injectToWireGuard err: %v", err)
return
// When failing to inject an outbound packet buffer, log the error, but
// continue serving the ReadContext for sending subsequent packets, as
// nothing manages or restarts a failed injectToWireGuard. An error here
// only applies to the current packet and should not terminate the long-lived
// packet pump.
// The exception to this is if the context has ended, indicating a shutdown.
if ns.ctx.Err() != nil {
return
}
continue
}
}
}
@@ -1097,7 +1106,16 @@ func (ns *Impl) injectToHost() {
}
if err := ns.tundev.InjectInboundPacketBuffer(pkt, inboundSlab, packets, writeBufs); err != nil {
ns.logf("netstack injectToHost err: %v", err)
return
// When failing to inject an outbound packet buffer, log the error, but
// continue serving the ReadContext for sending subsequent packets, as
// nothing manages or restarts a failed injectToHost. An error here
// only applies to the current packet and should not terminate the long-lived
// packet pump.
// The exception to this is if the context has ended, indicating a shutdown.
if ns.ctx.Err() != nil {
return
}
continue
}
}
}