Upstream acceptLoop treats any Accept error as terminal and silently
returns, leaving the stack alive but every new TCP SYN NAT-rewritten onto
a dead port (instant RST) until a full restart. When the listener fd is
closed out from under the stack (a stray close on a reused fd number from
another runtime in the same process), all new TCP dies forever while
UDP/QUIC/DNS keep working.
- System.Close() now marks a deliberate shutdown first; acceptLoop still
exits quietly on it.
- Any other Accept error is logged (the errno names the killer path),
the listener is recreated on the same address, the forwarder port is
republished atomically, and the loop keeps serving.
- If the rebind fails, the loop logs an error and gives up - no worse
than upstream.
- acceptRecoveries counter is kept as telemetry.
tcpPort/tcpPort6 become atomic (written by the heal path, read from the
tunLoop dispatch/NAT path); listener replacement is serialized against
Close() with a mutex.