commons-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Nils Martin Sande (JIRA)" <j...@apache.org>
Subject [jira] [Created] (NET-406) Improved disconnect handling in FtpClient: retrieveFile never returns under certain conditions and calling FtpClient.disconnect does not terminate the transfer.
Date Fri, 29 Apr 2011 10:37:03 GMT
Improved disconnect handling in FtpClient: retrieveFile never returns under certain conditions
and calling FtpClient.disconnect does not terminate the transfer.
----------------------------------------------------------------------------------------------------------------------------------------------------------------

                 Key: NET-406
                 URL: https://issues.apache.org/jira/browse/NET-406
             Project: Commons Net
          Issue Type: Improvement
          Components: FTP
    Affects Versions: 2.0
         Environment: Linux
            Reporter: Nils Martin Sande


During file download it is possible for the transfer to stop without any time out being triggered
in FtpClient. The result is a "lost" thread (it never returns from retrieveFile). Calling
interrupt on the missing thread does not do anything. 

When we encountered this error we fist tried to monitor the downloaded file and then call
FtpClient.disconnect if the size on disk remained unchanged for a given period of time. This
did not solve the problem since FtpClient.disconnect does not close the socket used by the
transfer. Changing FtpClient so that it keeps track of active sockets and then closing all
active sockets on FtpClient.disconnect solved the problem for us. Although this error is not
very common, the ability to completely kill the connection including all transfers seems like
a useful feature. I have included the details of the modifications we made, maybe someone
will find them useful. If there is a better way to get around this please let me know.

{code:title=FtpClient.java_retrieveFile|borderStyle=solid}
//The modified retrieveFile method (__activeSockets is a synchronized List<Socket>)
public boolean retrieveFile(String remote, OutputStream local)
            throws IOException {
        InputStream input;
        Socket socket;

        if ((socket = _openDataConnection_(FTPCommand.RETR, remote)) == null) {
            return false;
        }
        __activeSockets.add(socket);
        try {
            input = new BufferedInputStream(socket.getInputStream(),
                    getBufferSize());
            if (__fileType == ASCII_FILE_TYPE) {
                input = new FromNetASCIIInputStream(input);
            }
            // Treat everything else as binary for now
            try {
                Util.copyStream(input, local, getBufferSize(),
                        CopyStreamEvent.UNKNOWN_STREAM_SIZE, null,
                        false);
            } catch (IOException e) {
                try {
                    socket.close();
                } catch (IOException f) {
                }
                throw e;
            }
            socket.close();
            return completePendingCommand();
        } finally {
            __activeSockets.remove(socket);
        }
    }

//The modified disconnect method
public void disconnect() throws IOException {
        super.disconnect();
        __initDefaults();
        IOException exception = null;
        for (Socket socket : __activeSockets) {
            try {
                socket.close();
            } catch (IOException ex) {
                exception = ex;
            }
        }
        __activeSockets.clear();
        if (exception != null) {
            throw exception;
        }
    }
{code}



--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

Mime
View raw message