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] [Commented] (NET-406) Improved disconnect handling in FtpClient: retrieveFile never returns under certain conditions and calling FtpClient.disconnect does not terminate the transfer.
Date Tue, 03 May 2011 12:29:03 GMT

    [ https://issues.apache.org/jira/browse/NET-406?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13028183#comment-13028183
] 

Nils Martin Sande commented on NET-406:
---------------------------------------

We did play around with the various timeout settings, but I am unsure if that did work for
none or some of the cases.

I have updated the code base so that we use "FtpClient.setDataTimeout(timeout-5000)". The
timeout variable is set to 30000 and is used by the file size monitoring thread. This should
give us the answer to the "some cases or none" question". It can be several weeks between
each time the connection gets stuck so it might take some time (we are unable to reproduce
this at will).

I agree that a separate "terminate transfer" method would be better then the modified disconnect().
The code example is simply a minimum effort solution. The problem only appeared after the
move to production so we where a bit short on time.



> 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
>              Labels: features
>
> 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