From 6516c2d8f1dee003e0612055c5849b66c8b12021 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Wed, 17 Dec 2025 19:44:39 +0800 Subject: [PATCH] Fix race condition in ReadPacket --- tun_windows.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tun_windows.go b/tun_windows.go index e62789c..f33addf 100644 --- a/tun_windows.go +++ b/tun_windows.go @@ -395,15 +395,16 @@ retry: func (t *NativeTun) ReadPacket() ([]byte, func(), error) { t.running.Add(1) - defer t.running.Done() retry: if t.close.Load() == 1 { + t.running.Done() return nil, nil, os.ErrClosed } start := nanotime() shouldSpin := t.rate.current.Load() >= spinloopRateThreshold && uint64(start-t.rate.nextStartTime.Load()) <= rateMeasurementGranularity*2 for { if t.close.Load() == 1 { + t.running.Done() return nil, nil, os.ErrClosed } packet, err := t.session.ReceivePacket() @@ -411,7 +412,10 @@ retry: case nil: packetSize := len(packet) t.rate.update(uint64(packetSize)) - return packet, func() { t.session.ReleaseReceivePacket(packet) }, nil + return packet, func() { + t.session.ReleaseReceivePacket(packet) + t.running.Done() + }, nil case windows.ERROR_NO_MORE_ITEMS: if !shouldSpin || uint64(nanotime()-start) >= spinloopDuration { windows.WaitForSingleObject(t.readWait, windows.INFINITE) @@ -420,10 +424,13 @@ retry: procyield(1) continue case windows.ERROR_HANDLE_EOF: + t.running.Done() return nil, nil, os.ErrClosed case windows.ERROR_INVALID_DATA: + t.running.Done() return nil, nil, errors.New("send ring corrupt") } + t.running.Done() return nil, nil, fmt.Errorf("read failed: %w", err) } }