fix: wait for both goroutines before cleanup in HandleConnection
All checks were successful
renovate / renovate (push) Successful in 1m42s
Docker Build and Push / build-and-push-branches (push) Successful in 4m46s
Docker Build and Push / build-and-push-tags (push) Successful in 4m51s

Only waited for one of two copy goroutines, leaking the second. Now waits
for both to complete before closing connections.

Fixes file descriptor leak causing 'too many open files' under load.

Fixes: #56
This commit is contained in:
2025-12-31 22:22:51 +07:00
parent 9276430fae
commit b115369913

View File

@@ -152,25 +152,26 @@ func (f *Forwarder) HandleConnection(dst io.ReadWriter, src ssh.Channel, remoteA
log.Printf("Handling new forwarded connection from %s", remoteAddr) log.Printf("Handling new forwarded connection from %s", remoteAddr)
done := make(chan struct{}, 2) var wg sync.WaitGroup
wg.Add(2)
go func() {
_, err := copyWithBuffer(src, dst)
if err != nil && !errors.Is(err, io.EOF) && !errors.Is(err, net.ErrClosed) {
log.Printf("Error copying from conn.Reader to channel: %v", err)
}
done <- struct{}{}
}()
go func() { go func() {
defer wg.Done()
_, err := copyWithBuffer(dst, src) _, err := copyWithBuffer(dst, src)
if err != nil && !errors.Is(err, io.EOF) && !errors.Is(err, net.ErrClosed) { if err != nil && !errors.Is(err, io.EOF) && !errors.Is(err, net.ErrClosed) {
log.Printf("Error copying from channel to conn.Writer: %v", err) log.Printf("Error copying src→dst: %v", err)
} }
done <- struct{}{}
}() }()
<-done go func() {
defer wg.Done()
_, err := copyWithBuffer(src, dst)
if err != nil && !errors.Is(err, io.EOF) && !errors.Is(err, net.ErrClosed) {
log.Printf("Error copying dst→src: %v", err)
}
}()
wg.Wait()
} }
func (f *Forwarder) SetType(tunnelType types.TunnelType) { func (f *Forwarder) SetType(tunnelType types.TunnelType) {