Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 358147

Summary: jetty client socket fd leak when access an URL with bad domain
Product: [RT] Jetty Reporter: Junwei Sun <sunjunwei2>
Component: clientAssignee: Jesse McConnell <jesse.mcconnell>
Status: RESOLVED FIXED QA Contact:
Severity: critical    
Priority: P3 CC: gregw, janb, jesse.mcconnell, jetty-inbox
Version: unspecified   
Target Milestone: 7.5.x   
Hardware: PC   
OS: Linux   
See Also: https://bugs.eclipse.org/bugs/show_bug.cgi?id=358959
Whiteboard:
Attachments:
Description Flags
simple test
none
proposed patch
none
proposed patch none

Description Junwei Sun CLA 2011-09-19 13:54:47 EDT
Build Identifier: 7.4.5.v20110725

jetty client socket fd leak when access an URL with bad domain

I'm using jetty client(jetty-client-7.4.5.v20110725)as http client to
download html pages, but find that jetty client has socket fd leak
issue.
When jetty client download a URL which domain can not be resolved, it
will leak a socket fd, such as URL "http://com.br/".
It will throw an UnresolvedAddressException:

[05 Sep 2011 11:10:55] [main] [Slf4jLog.java:80] [DEBUG] EXCEPTION 
java.nio.channels.UnresolvedAddressException
        at sun.nio.ch.Net.checkAddress(Net.java:30)
        at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:487)
        at
org.eclipse.jetty.client.SelectConnector.startConnection(SelectConnector.java:99)
        at
org.eclipse.jetty.client.HttpDestination.startNewConnection(HttpDestination.java:265)
        at
org.eclipse.jetty.client.HttpDestination.doSend(HttpDestination.java:552)
        at
org.eclipse.jetty.client.HttpDestination.send(HttpDestination.java:490)
        at org.eclipse.jetty.client.HttpClient.send(HttpClient.java:178)
        at cn.vobile.colander.Crawler.Crawler.addCrawlRequest(Crawler.java:138)
        at cn.vobile.colander.Crawler.Crawler.main(Crawler.java:438)
[05 Sep 2011 11:10:56] [main] [Slf4jLog.java:50] [WARN] CONNECTION
FAILED CrawlExchange@1309073=GET//com.br:80/#9

Then, a socket fd leaked, just like the following fd:

$ lsof -p 4499|grep sock
java    4499 sunjw   41r  sock        0,6      0t0  151513 can't
identify protocol
java    4499 sunjw   42r  unix 0xf4ffc700      0t0  151855 socket
java    4499 sunjw   43r  sock        0,6      0t0  151515 can't
identify protocol

Is there any method of http client to close these socket(s)?

I understand jetty client has feature to manage connection pool. 
However, in this case, the URL is a bad URL which domain does not exist.
So, there is no connection for this URL at all actually. But the socket fd leaves there, never disappears!
Even I set the idle timeout to be very small, the socket fd is still there.
When I submit more of such URLs' requests, socket fd number increases
more and more. At last, the program dies.
So from my point of view, this issue should be a bug in jetty client code.

The reproducing code is: 

             HttpClient hc = new HttpClient();
             hc.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
             hc.setMaxConnectionsPerAddress(1);
             hc.setConnectBlocking(false);
             hc.setIdleTimeout(10 * 1000L);
             hc.setThreadPool(new QueuedThreadPool(3));
             hc.setTimeout(60000);
             hc.start();
             ContentExchange ce = new ContentExchange();
             ce.setURL("http://com.br");
             hc.send(ce);
             log.info("sended, waitForDone");
             ce.waitForDone();
             log.info("done, sleeping");
             Thread.sleep(100*1000L);

Thanks.

-- 
Best Regards,
Junwei

Reproducible: Always

Steps to Reproduce:
1. execute above code.
2. use lsof to probe how many socket fd the program uses.
Comment 1 Greg Wilkins CLA 2011-09-20 03:52:21 EDT
Created attachment 203644 [details]
simple test
Comment 2 Greg Wilkins CLA 2011-09-20 03:54:01 EDT
oops this attachment was for 346419, which looks to be very similar.
Comment 3 Thomas Becker CLA 2011-09-20 04:21:58 EDT
Created attachment 203647 [details]
proposed patch
Comment 4 Thomas Becker CLA 2011-09-20 04:23:42 EDT
Created attachment 203648 [details]
proposed patch

Hi Simone, Greg,

please find attached two patch files. The first commit is only a codeformat and the second catches the Exception, closes the connection and rethrows the RuntimeException.

Cheers,
Thomas
Comment 5 Junwei Sun CLA 2011-09-20 14:31:29 EDT
Hi Thomas,

Thanks for the fast reply. I've reviewed the code that handles one exception "UnresolvedAddressException". Actually, there are two exceptions, another one is "UnknownHostException" when I have code "httpclient.setConnectBlocking(true)".

I think we need to handle all of these exceptions to avoid fd leak.

Regards,
Junwei
Comment 6 Jesse McConnell CLA 2011-09-20 15:22:23 EDT
applied the first two patches, will address the other issue mentioned and then push the commits
Comment 7 Junwei Sun CLA 2011-09-22 13:50:00 EDT
So which release will include this issue fix?
(In reply to comment #6)
> applied the first two patches, will address the other issue mentioned and then
> push the commits
Comment 8 Junwei Sun CLA 2011-10-07 13:54:37 EDT
Hi All,

I've tested the latest release http://download.eclipse.org/jetty/7.5.2.v20111006/dist/jetty-distribution-7.5.2.v20111006.tar.gz. The socket fd leak issue still exists. It's not been fixed in this release:

$ lsof -p11016|grep sock
java    11016 sunjw   40r  sock                0,7      0t0 169110 can't identify protocol
java    11016 sunjw   41r  unix 0x0000000000000000      0t0 170810 socket
java    11016 sunjw   42r  sock                0,7      0t0 169112 can't identify protocol
Comment 9 Junwei Sun CLA 2011-10-07 14:07:49 EDT
(In reply to comment #8)
> Hi All,
> 
> I've tested the latest release
> http://download.eclipse.org/jetty/7.5.2.v20111006/dist/jetty-distribution-7.5.2.v20111006.tar.gz.
> The socket fd leak issue still exists. It's not been fixed in this release:
> 
> $ lsof -p11016|grep sock
> java    11016 sunjw   40r  sock                0,7      0t0 169110 can't
> identify protocol
> java    11016 sunjw   41r  unix 0x0000000000000000      0t0 170810 socket
> java    11016 sunjw   42r  sock                0,7      0t0 169112 can't
> identify protocol

Currently, the code will catch IOException. But UnresolvedAddressException is not an IOException!! Thus, the exception is still not processed correctly.

java.lang.Object
java.lang.Throwable
java.lang.Exception
java.lang.RuntimeException
java.lang.IllegalArgumentException
java.nio.channels.UnresolvedAddressException

Regards.
Junwei
Comment 10 Jan Bartel CLA 2011-10-09 22:11:11 EDT
This bug is the same as https://bugs.eclipse.org/bugs/show_bug.cgi?id=358959.

Unfortunately, I misread the inheritance of the UnresolvedAddressException for that one, so it isn't caught by the try/catch of IOException. Note that UnknownHostException IS an IOException so was handled anyway.


I've now fixed the SelectorConnector to catch UnresolvedAddressException. This will be in jetty-7.5.3.

Jan