Release resources in client Transport.Dial on error.

Make a stack of cleanup functions to run (as with defer), but clear the
stack before returning if no error occurs.

Uselessly pushing the stream.Close() cleanup just before clearing the
stack is an intentional safeguard, for in case additional operations are
added before the return in the future.

Fixes #40042.
This commit is contained in:
David Fifield 2021-05-24 15:09:29 -06:00
parent 01a96c7d95
commit ae7cc478fd

View file

@ -74,11 +74,21 @@ func NewSnowflakeClient(brokerURL, frontDomain string, iceAddresses []string, ke
// Create a new Snowflake connection. Starts the collection of snowflakes and returns a // Create a new Snowflake connection. Starts the collection of snowflakes and returns a
// smux Stream. // smux Stream.
func (t *Transport) Dial() (net.Conn, error) { func (t *Transport) Dial() (net.Conn, error) {
// Cleanup functions to run before returning, in case of an error.
var cleanup []func()
defer func() {
// Run cleanup in reverse order, as defer does.
for i := len(cleanup) - 1; i >= 0; i-- {
cleanup[i]()
}
}()
// Prepare to collect remote WebRTC peers. // Prepare to collect remote WebRTC peers.
snowflakes, err := NewPeers(t.dialer) snowflakes, err := NewPeers(t.dialer)
if err != nil { if err != nil {
return nil, err return nil, err
} }
cleanup = append(cleanup, func() { snowflakes.End() })
// Use a real logger to periodically output how much traffic is happening. // Use a real logger to periodically output how much traffic is happening.
snowflakes.BytesLogger = NewBytesSyncLogger() snowflakes.BytesLogger = NewBytesSyncLogger()
@ -92,15 +102,22 @@ func (t *Transport) Dial() (net.Conn, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
cleanup = append(cleanup, func() {
pconn.Close()
sess.Close()
})
// On the smux session we overlay a stream. // On the smux session we overlay a stream.
stream, err := sess.OpenStream() stream, err := sess.OpenStream()
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Begin exchanging data. // Begin exchanging data.
log.Printf("---- SnowflakeConn: begin stream %v ---", stream.ID()) log.Printf("---- SnowflakeConn: begin stream %v ---", stream.ID())
cleanup = append(cleanup, func() { stream.Close() })
// All good, clear the cleanup list.
cleanup = nil
return &SnowflakeConn{Stream: stream, sess: sess, pconn: pconn, snowflakes: snowflakes}, nil return &SnowflakeConn{Stream: stream, sess: sess, pconn: pconn, snowflakes: snowflakes}, nil
} }