浏览代码

Merge pull request #87 from DAddYE/patch-1

Avoid forever lock
Julien Laffaye 8 年之前
父节点
当前提交
5c7b901224
共有 2 个文件被更改,包括 12 次插入5 次删除
  1. 1 0
      client_test.go
  2. 11 5
      ftp.go

+ 1 - 0
client_test.go

@@ -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

+ 11 - 5
ftp.go

@@ -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
-	c    *ServerConn
+	conn   net.Conn
+	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
 }
 }