fix(tunnel): data race in CloseOnIdle and goroutine leak in sniffingWebsocketFrame
- Use write lock (Lock) instead of read lock (RLock) in CloseOnIdle since it modifies the close channel, preventing a race with Close() that could panic on double-close of channel. - Buffer sniffingWebsocketFrame errc to capacity 2 and close both connections on first error to ensure the remaining copy goroutine unblocks and exits cleanly.
This commit is contained in:
@@ -440,8 +440,8 @@ func (ep *entrypoint) handleUpgradeResponse(ctx context.Context, rw io.ReadWrite
|
||||
return xnet.Pipe(ctx, rw, backConn)
|
||||
}
|
||||
|
||||
func (ep *entrypoint) sniffingWebsocketFrame(ctx context.Context, rw, cc io.ReadWriter, ro *xrecorder.HandlerRecorderObject, log logger.Logger) error {
|
||||
errc := make(chan error, 1)
|
||||
func (ep *entrypoint) sniffingWebsocketFrame(ctx context.Context, rw, cc io.ReadWriteCloser, ro *xrecorder.HandlerRecorderObject, log logger.Logger) error {
|
||||
errc := make(chan error, 2)
|
||||
|
||||
sampleRate := ep.websocketSampleRate
|
||||
if sampleRate == 0 {
|
||||
@@ -503,6 +503,9 @@ func (ep *entrypoint) sniffingWebsocketFrame(ctx context.Context, rw, cc io.Read
|
||||
}
|
||||
}()
|
||||
|
||||
<-errc
|
||||
rw.Close()
|
||||
cc.Close()
|
||||
<-errc
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -230,8 +230,8 @@ func (t *Tunnel) Close() error {
|
||||
}
|
||||
|
||||
func (t *Tunnel) CloseOnIdle() bool {
|
||||
t.mu.RLock()
|
||||
defer t.mu.RUnlock()
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
select {
|
||||
case <-t.close:
|
||||
|
||||
Reference in New Issue
Block a user