You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "Laurent Chiarello (JIRA)" <ji...@apache.org> on 2018/09/26 11:36:00 UTC

[jira] [Comment Edited] (CAMEL-12830) FTP producer stuck if timeout occurs just after connect

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

Laurent Chiarello edited comment on CAMEL-12830 at 9/26/18 11:35 AM:
---------------------------------------------------------------------

The suggestion I made was more a workaround than a true fix. I attached a patch with another fix that tackles the true issue: a _logout_ should not be performed if the _connect_ was not successful.

If an exception is raised during the _connect_ of the {{FtpClient}}, a _disconnect_ should be issued to ensure that the underlying {{Socket}} is properly closed and disposed. This also avoids potential resources leaks (in the situation of a server accepting connections without sending FTP replies, each reconnect attempt created and connected a new Socket without closing the previous one).


was (Author: lchdev):
The suggestion I made was more a workaround than a true fix. I attached a patch with another fix that tackles the true issue: a _logout_ should not be performed if the _connect_ was not successful.

If an exception is raised during the _connect_ of the {{FtpClient}}, a _disconnect_ should be issued to ensure that the underlying {{Socket}} is properly closed and disposed. This also avoids potential resources leaks (in the situation of a server accepting connections without sending FTP replies, each reconnected attempt creates and connects a new Socket without closing the previous one).

> FTP producer stuck if timeout occurs just after connect
> -------------------------------------------------------
>
>                 Key: CAMEL-12830
>                 URL: https://issues.apache.org/jira/browse/CAMEL-12830
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-ftp
>    Affects Versions: 2.22.1
>            Reporter: Laurent Chiarello
>            Priority: Major
>         Attachments: FtpOperations.patch, FtpSoTimeoutTest.java
>
>
> In our production systems, we had several threads stuck indefinitely while trying to send a file to an FtpEndpoint. We had both _connectTimeout_ and _soTimeout_ properties set so it surprised us a little bit.
> After digging a bit, we found that the scenario is quite simple to reproduce: this happens every time the {{FTPClient}} establishes the TCP connection with a server that does not respond anything.
> Here is a simplified view of what happens when establishing a connection using a {{FTPClient}}:
> {code:java}
> // within Socket Client
> public void connect(InetAddress host, int port) throws SocketException,IOException {
>     _socket_.connect(new InetSocketAddress(host, port), connectTimeout);
>     _connectAction_();
> }
> protected void _connectAction_() throws IOException { 
>     _socket_.setSoTimeout(_timeout_); // _timeout_ is the default timeout of the socket
> }
> // overridden within FTP
> protected void _connectAction_() {
>     super._connectAction_();
>     if (connectTimeout > 0) {
>         int original = _socket_.getSoTimeout();
>         _socket_.setSoTimeout(connectTimeout);
>         try {
>             __getReply();
>         } finally {
>              _socket_.setSoTimeout(original);
>         }
>     }
> }{code}
>  A {{SocketTimeoutException}} can be thrown either during the initial socket _connect_ action, either during the ___getReply()_ where the FTPClient waits for the hello message from the server.  Both are using _connectTimeout_, after which the original (default) timeout is restored. The _soTimeout_ we specified in the URI is configured by FTPOperations only when the connection is successful. In this case, the Socket is connected, but an exception is thrown afterwards and the _soTimeout_ is left at 0. 
> Within Camel, when the RemoteFileProducer encounters an exception while processing an Exchange, it tries to disconnect the endpoint properly with a _logout_ followed by a _disconnect_. 
> {code:java}
> // RemoteFileProducer
> public void handleFailedWrite(Exchange exchange, Exception exception) throws Exception {
>     try {
>         if (getOperations().isConnected()) { // <== in our case, this returns true because the socket is actually connected
>             getOperations().disconnect();
>         }
>     } catch (...) {
>         ...
>     }
> }
> // FTPOperations
> protected void doDisconnect() throws GenericFileOperationFailedException {
>     try {
>         client.logout();
>     } catch (IOException e) {
>          throw new GenericFileOperationFailedException
>     } finally {
>         try {
>             client.disconnect();
>         } catch (IOException e) {
>             throw new GenericFileOperationFailedException
>         }
>     }
> }{code}
> Unfortunately, at this point, the {{client.logout()}} sends the FTP {{QUIT}} command, then waits for the response still using the default timeout of the Socket. Since the misbehaving server/firewall never sent any form of response, the thread is left waiting forever.
> I attached a simple test case to illustrate the scenario, simply using a ServerSocket that never accepts any connection. Also included is an easy workaround that uses a custom FTPClient on which the _default timeout_ is set. 
> A possible fix would be to always set the _default timeout_ on the socket, before connecting it.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)