Fixed bug where tried closing a single net.Conn multiple times.
This commit is contained in:
parent
d2cac01b63
commit
325901c2c3
18
dialer.go
18
dialer.go
|
@ -2,6 +2,7 @@ package goadb
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"runtime"
|
||||
|
||||
|
@ -66,17 +67,22 @@ func (d *netDialer) Dial() (*wire.Conn, error) {
|
|||
}
|
||||
}
|
||||
|
||||
conn := &wire.Conn{
|
||||
Scanner: wire.NewScanner(netConn),
|
||||
Sender: wire.NewSender(netConn),
|
||||
}
|
||||
// net.Conn can't be closed more than once, but wire.Conn will try to close both sender and scanner
|
||||
// so we need to wrap it to make it safe.
|
||||
safeConn := wire.MultiCloseable(netConn)
|
||||
|
||||
// Prevent leaking the network connection, not sure if TCPConn does this itself.
|
||||
runtime.SetFinalizer(netConn, func(conn *net.TCPConn) {
|
||||
// Note that the network connection may still be in use after the conn isn't (scanners/senders
|
||||
// can give their underlying connections to other scanner/sender types), so we can't
|
||||
// set the finalizer on conn.
|
||||
runtime.SetFinalizer(safeConn, func(conn io.ReadWriteCloser) {
|
||||
conn.Close()
|
||||
})
|
||||
|
||||
return conn, nil
|
||||
return &wire.Conn{
|
||||
Scanner: wire.NewScanner(safeConn),
|
||||
Sender: wire.NewSender(safeConn),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func roundTripSingleResponse(d Dialer, req string) ([]byte, error) {
|
||||
|
|
|
@ -66,7 +66,7 @@ func (w *syncFileWriter) Close() error {
|
|||
}
|
||||
|
||||
if err := w.sender.SendOctetString(wire.StatusSyncDone); err != nil {
|
||||
return util.WrapErrf(err, "error closing file writer")
|
||||
return util.WrapErrf(err, "error sending done chunk to close stream")
|
||||
}
|
||||
if err := w.sender.SendTime(w.mtime); err != nil {
|
||||
return util.WrapErrf(err, "error writing file modification time")
|
||||
|
|
20
wire/util.go
20
wire/util.go
|
@ -5,6 +5,8 @@ import (
|
|||
"io"
|
||||
"regexp"
|
||||
|
||||
"sync"
|
||||
|
||||
"github.com/zach-klippenstein/goadb/util"
|
||||
)
|
||||
|
||||
|
@ -80,3 +82,21 @@ func writeFully(w io.Writer, data []byte) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MultiCloseable wraps c in a ReadWriteCloser that can be safely closed multiple times.
|
||||
func MultiCloseable(c io.ReadWriteCloser) io.ReadWriteCloser {
|
||||
return &multiCloseable{ReadWriteCloser: c}
|
||||
}
|
||||
|
||||
type multiCloseable struct {
|
||||
io.ReadWriteCloser
|
||||
closeOnce sync.Once
|
||||
err error
|
||||
}
|
||||
|
||||
func (c *multiCloseable) Close() error {
|
||||
c.closeOnce.Do(func() {
|
||||
c.err = c.ReadWriteCloser.Close()
|
||||
})
|
||||
return c.err
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue