diff --git a/pkg/client/tunnel.go b/pkg/client/tunnel.go index 1332204..fd3558a 100644 --- a/pkg/client/tunnel.go +++ b/pkg/client/tunnel.go @@ -50,20 +50,23 @@ func NewTunnel(sess *Session) *Tunnel { // writeLoop is the single goroutine that writes to the connection. // All writes are serialized through writeCh — no mutex needed. func (t *Tunnel) writeLoop() { - for buf := range t.writeCh { - if _, err := t.sess.Conn.Write(buf); err != nil { - t.writeErr = err + for { + select { + case buf := <-t.writeCh: + if _, err := t.sess.Conn.Write(buf); err != nil { + t.writeErr = err + return + } + case <-t.stopCh: return } } } // Close stops the keepalive goroutine and closes the underlying connection. +// The writeCh is not closed here — writeLoop exits when the connection write fails. func (t *Tunnel) Close() error { - t.stopped.Do(func() { - close(t.stopCh) - close(t.writeCh) - }) + t.stopped.Do(func() { close(t.stopCh) }) return t.sess.Conn.Close() }