refactor(proxy): simplify tunnel tracking with mutex-only approach

Remove atomic counter in favor of simple int protected by mutex.
Eliminates race condition complexity and recheck logic.
This commit is contained in:
Laurence
2026-03-13 16:36:56 +00:00
parent 28c65b950c
commit d21c09c84f

View File

@@ -14,7 +14,6 @@ import (
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
"github.com/fosrl/gerbil/logger"
@@ -76,7 +75,7 @@ type SNIProxy struct {
type activeTunnel struct {
ctx context.Context
cancel context.CancelFunc
count atomic.Int64
count int // protected by activeTunnelsLock
}
// readOnlyConn is a wrapper for io.Reader that implements net.Conn
@@ -600,21 +599,18 @@ func (p *SNIProxy) handleConnection(clientConn net.Conn) {
tunnel = &activeTunnel{ctx: ctx, cancel: cancel}
p.activeTunnels[hostname] = tunnel
}
tunnel.count.Add(1)
tunnel.count++
tunnelCtx := tunnel.ctx
p.activeTunnelsLock.Unlock()
defer func() {
// Decrement count atomically; if we're the last connection, clean up
if tunnel.count.Add(-1) == 0 {
p.activeTunnelsLock.Lock()
tunnel.count--
if tunnel.count == 0 {
tunnel.cancel()
p.activeTunnelsLock.Lock()
// Only delete if the map still points to our tunnel
if p.activeTunnels[hostname] == tunnel {
delete(p.activeTunnels, hostname)
}
p.activeTunnelsLock.Unlock()
delete(p.activeTunnels, hostname)
}
p.activeTunnelsLock.Unlock()
}()
// Start bidirectional data transfer with tunnel context