[
https://issues.apache.org/jira/browse/HTTPCLIENT-747?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12579008#action_12579008
]
Sam Berlin commented on HTTPCLIENT-747:
---------------------------------------
Some more investigation & some (possible?) bugs:
It doesn't look like entries are cleaned up correctly if the socket connection
fails. DefaultClientRequestDirector.execute allocates an entry for a route
before opening a connection. Then if there's an exception while opening the
socket, it doesn't look like the entry is freed up. That means that subsequent
requests to the same route will fail (if it's over the maximum limit per host).
This explains why it took so long to create a third entry after the first two
failed -- it happened whenever the system just-so-happened to GC. (I suspect
this is also a problem with exceptions during normal i/o exchange, but I'm not
sure.)
It also doesn't look like 'abort' will correctly terminate a connection that's
waiting to receive a ManagedClientConnection from the ClientConnectionManager.
There's an abort sequence set on the HttpUriRequest, but it's set to be the
ManagedClientConnection, which is only created when allocateConnection returns.
This explains why it tried to create an entry after an abort was called,
because the wait-for-connection didn't finish. Normally I would suggest
requiring the caller to call Thread.interupt() to abort the wait, but that
isn't terribly safe, especially with I/O being performed on that thread --
there's no way to know from the outside if the internals have succeeded in
getting a connection and moved onto I/O. There's two ways of fixing it that I
can see -- one is to add a releaseTrigger prior to calling allocateConnection
that just calls Thread.interrupt(), and then overwriting it afterwards.
Another way is to pass the AbortableHttpRequest down the chain eventually into
ConnPoolByRoute.getEntry and let it install a more proper releaseTrigger ,
probably using a method in WaitingThread that signals completion but has await
return false (it could also use Thread.interrupt, I'm just not the biggest fan
of that method).
I'm still boggled by the freeEntry call. It's as if a connection succeeded,
but one with an entirely different RouteSpecificPool. No clue on how to
explain that one.
> No entry created for this pool.
> -------------------------------
>
> Key: HTTPCLIENT-747
> URL: https://issues.apache.org/jira/browse/HTTPCLIENT-747
> Project: HttpComponents HttpClient
> Issue Type: Bug
> Components: HttpConn
> Affects Versions: 4.0 Alpha 3
> Reporter: Roland Weber
> Priority: Minor
> Fix For: 4.0 Alpha 4
>
>
> Followup to https://issues.apache.org/jira/browse/HTTPCLIENT-741, as reported
> by Sam Berlin:
> java.lang.IllegalStateException: No entry created for this pool.
> HttpRoute[{}->http://74.160.66.42:14561]
> at
> org.apache.http.impl.conn.tsccm.RouteSpecificPool.freeEntry(RouteSpecificPool.java:137)
> at
> org.apache.http.impl.conn.tsccm.ConnPoolByRoute.freeEntry(ConnPoolByRoute.java:337)
> at
> org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager.releaseConnection(ThreadSafeClientConnManager.java:230)
> at
> org.apache.http.impl.client.DefaultClientRequestDirector.execute(DefaultClientRequestDirector.java:427)
> at
> org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:500)
> at
> org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:455)
> at
> org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:421)
> at
> com.limegroup.gnutella.http.DefaultHttpExecutor.performRequest(DefaultHttpExecutor.java:97)
> at
> com.limegroup.gnutella.http.DefaultHttpExecutor.access$000(DefaultHttpExecutor.java:26)
> at
> com.limegroup.gnutella.http.DefaultHttpExecutor$MultiRequestor.run(DefaultHttpExecutor.java:139)
> at
> org.limewire.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1006)
> at
> org.limewire.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:549)
> at java.lang.Thread.run(Thread.java:613)
> ---
> DefaultHttpExecutor$MultiRequestor basically is just a Runnable / Cancellable
> [exposes a cancel() method] that can be cancelled from any thread. cancel
> just calls abort() on the current AbortableHttpRequest, but is called on a
> thread other than the one that's doing the client.execute(request).
> The last one is the most common exception, and seems to happen with some
> regularity. The other two we've only seen once, so may just be a memory quirk
> (we've seen some crazy bugs, including recursive NPEs while constructing an
> NPE.)
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]