Fixed bug where tried closing a single net.Conn multiple times.

This commit is contained in:
Zach Klippenstein 2015-12-30 00:00:03 -08:00
parent d2cac01b63
commit 325901c2c3
3 changed files with 33 additions and 7 deletions

View file

@ -2,6 +2,7 @@ package goadb
import ( import (
"fmt" "fmt"
"io"
"net" "net"
"runtime" "runtime"
@ -66,17 +67,22 @@ func (d *netDialer) Dial() (*wire.Conn, error) {
} }
} }
conn := &wire.Conn{ // net.Conn can't be closed more than once, but wire.Conn will try to close both sender and scanner
Scanner: wire.NewScanner(netConn), // so we need to wrap it to make it safe.
Sender: wire.NewSender(netConn), safeConn := wire.MultiCloseable(netConn)
}
// Prevent leaking the network connection, not sure if TCPConn does this itself. // 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() 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) { func roundTripSingleResponse(d Dialer, req string) ([]byte, error) {

View file

@ -66,7 +66,7 @@ func (w *syncFileWriter) Close() error {
} }
if err := w.sender.SendOctetString(wire.StatusSyncDone); err != nil { 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 { if err := w.sender.SendTime(w.mtime); err != nil {
return util.WrapErrf(err, "error writing file modification time") return util.WrapErrf(err, "error writing file modification time")

View file

@ -5,6 +5,8 @@ import (
"io" "io"
"regexp" "regexp"
"sync"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/util"
) )
@ -80,3 +82,21 @@ func writeFully(w io.Writer, data []byte) error {
} }
return nil 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
}