2020-05-11 20:57:46 +02:00
|
|
|
// Copyright (C) 2019 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package netutil
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net"
|
|
|
|
"runtime"
|
|
|
|
)
|
|
|
|
|
|
|
|
// closeTrackingConn wraps a net.Conn and keeps track of if it was closed
|
2020-05-29 15:08:11 +02:00
|
|
|
// or if it was leaked (and closes it if it was leaked).
|
2020-05-11 20:57:46 +02:00
|
|
|
type closeTrackingConn struct {
|
|
|
|
net.Conn
|
|
|
|
}
|
|
|
|
|
|
|
|
// TrackClose wraps the conn and sets a finalizer on the returned value to
|
|
|
|
// close the conn and monitor that it was leaked.
|
|
|
|
func TrackClose(conn net.Conn) net.Conn {
|
|
|
|
tracked := &closeTrackingConn{Conn: conn}
|
|
|
|
runtime.SetFinalizer(tracked, (*closeTrackingConn).finalize)
|
|
|
|
return tracked
|
|
|
|
}
|
|
|
|
|
|
|
|
// Close clears the finalizer and closes the connection.
|
|
|
|
func (c *closeTrackingConn) Close() error {
|
|
|
|
runtime.SetFinalizer(c, nil)
|
|
|
|
mon.Event("connection_closed")
|
|
|
|
return c.Conn.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
// finalize monitors that a connection was leaked and closes the connection.
|
|
|
|
func (c *closeTrackingConn) finalize() {
|
|
|
|
mon.Event("connection_leaked")
|
|
|
|
_ = c.Conn.Close()
|
|
|
|
}
|