Fix flow close race
This commit is contained in:
parent
b59636919c
commit
e5c21070ae
1 changed files with 26 additions and 4 deletions
|
|
@ -3,6 +3,7 @@ package tun
|
||||||
import (
|
import (
|
||||||
"maps"
|
"maps"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -113,6 +114,7 @@ type ForwardDispatcher struct {
|
||||||
logger logger.Logger
|
logger logger.Logger
|
||||||
udpTimeout time.Duration
|
udpTimeout time.Duration
|
||||||
icmpTimeout time.Duration
|
icmpTimeout time.Duration
|
||||||
|
access sync.RWMutex
|
||||||
|
|
||||||
table map[flowKey]*flowEntry
|
table map[flowKey]*flowEntry
|
||||||
lastSweep int64
|
lastSweep int64
|
||||||
|
|
@ -168,26 +170,41 @@ func (d *ForwardDispatcher) Close() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
d.returnPath.closed.Store(true)
|
d.returnPath.closed.Store(true)
|
||||||
|
d.access.Lock()
|
||||||
|
flows := make([]*forwardFlow, 0, len(d.table))
|
||||||
for _, entry := range d.table {
|
for _, entry := range d.table {
|
||||||
if entry.flow != nil {
|
if entry.flow != nil {
|
||||||
entry.flow.close(FlowCloseReset)
|
flows = append(flows, entry.flow)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ports := make([]Port, 0, len(d.ports))
|
||||||
for port, nat := range d.ports {
|
for port, nat := range d.ports {
|
||||||
if nat != nil {
|
if nat != nil {
|
||||||
port.DetachReturn(&d.returnPath)
|
ports = append(ports, port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
d.access.Unlock()
|
||||||
|
for _, flow := range flows {
|
||||||
|
flow.close(FlowCloseReset)
|
||||||
|
}
|
||||||
|
for _, port := range ports {
|
||||||
|
port.DetachReturn(&d.returnPath)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *ForwardDispatcher) Dispatch(packet []byte) bool {
|
func (d *ForwardDispatcher) Dispatch(packet []byte) bool {
|
||||||
if d == nil {
|
if d == nil || d.returnPath.closed.Load() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
parsed, ok := parseForwardPacket(packet)
|
parsed, ok := parseForwardPacket(packet)
|
||||||
if !ok || parsed.fragment || !parsed.hasFlow {
|
if !ok || parsed.fragment || !parsed.hasFlow {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
d.access.RLock()
|
||||||
|
defer d.access.RUnlock()
|
||||||
|
if d.returnPath.closed.Load() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
key := parsed.flowKey()
|
key := parsed.flowKey()
|
||||||
now := d.now()
|
now := d.now()
|
||||||
entry, loaded := d.table[key]
|
entry, loaded := d.table[key]
|
||||||
|
|
@ -553,7 +570,12 @@ func (d *ForwardDispatcher) ResetNetwork() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *ForwardDispatcher) Flush() {
|
func (d *ForwardDispatcher) Flush() {
|
||||||
if d == nil {
|
if d == nil || d.returnPath.closed.Load() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
d.access.RLock()
|
||||||
|
defer d.access.RUnlock()
|
||||||
|
if d.returnPath.closed.Load() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if d.resetPending.Swap(false) {
|
if d.resetPending.Swap(false) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue