Merge pull request #87 from DAddYE/patch-1

Avoid forever lock
This commit is contained in:
Julien Laffaye 2017-05-07 20:23:38 +02:00 committed by GitHub
commit 5c7b901224
2 changed files with 12 additions and 5 deletions

View File

@ -81,6 +81,7 @@ func testConn(t *testing.T, disableEPSV bool) {
t.Errorf("'%s'", buf) t.Errorf("'%s'", buf)
} }
r.Close() r.Close()
r.Close() // test we can close two times
} }
// Read with deadline // Read with deadline

16
ftp.go
View File

@ -47,8 +47,9 @@ type Entry struct {
// Response represents a data-connection // Response represents a data-connection
type Response struct { type Response struct {
conn net.Conn conn net.Conn
c *ServerConn c *ServerConn
closed bool
} }
// Connect is an alias to Dial, for backward compatibility // Connect is an alias to Dial, for backward compatibility
@ -337,7 +338,7 @@ func (c *ServerConn) NameList(path string) (entries []string, err error) {
return return
} }
r := &Response{conn, c} r := &Response{conn: conn, c: c}
defer r.Close() defer r.Close()
scanner := bufio.NewScanner(r) scanner := bufio.NewScanner(r)
@ -368,7 +369,7 @@ func (c *ServerConn) List(path string) (entries []*Entry, err error) {
return return
} }
r := &Response{conn, c} r := &Response{conn: conn, c: c}
defer r.Close() defer r.Close()
scanner := bufio.NewScanner(r) scanner := bufio.NewScanner(r)
@ -445,7 +446,7 @@ func (c *ServerConn) RetrFrom(path string, offset uint64) (*Response, error) {
return nil, err return nil, err
} }
return &Response{conn, c}, nil return &Response{conn: conn, c: c}, nil
} }
// Stor issues a STOR FTP command to store a file to the remote FTP server. // Stor issues a STOR FTP command to store a file to the remote FTP server.
@ -536,12 +537,17 @@ func (r *Response) Read(buf []byte) (int, error) {
} }
// Close implements the io.Closer interface on a FTP data connection. // Close implements the io.Closer interface on a FTP data connection.
// After the first call, Close will do nothing and return nil.
func (r *Response) Close() error { func (r *Response) Close() error {
if r.closed {
return nil
}
err := r.conn.Close() err := r.conn.Close()
_, _, err2 := r.c.conn.ReadResponse(StatusClosingDataConnection) _, _, err2 := r.c.conn.ReadResponse(StatusClosingDataConnection)
if err2 != nil { if err2 != nil {
err = err2 err = err2
} }
r.closed = true
return err return err
} }