[jira] Created: (HTTPCLIENT-881) AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect

View: New views
11 Messages — Rating Filter:   Alert me  

[jira] Created: (HTTPCLIENT-881) AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect

by JIRA jira@apache.org :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect
---------------------------------------------------------------------------------------------------------------------------------

                 Key: HTTPCLIENT-881
                 URL: https://issues.apache.org/jira/browse/HTTPCLIENT-881
             Project: HttpComponents HttpClient
          Issue Type: Bug
          Components: HttpClient
    Affects Versions: 4.0 Final
            Reporter: Tim Boemker
            Priority: Minor


If HttpUriRequest.abort() is called at about the same time that the request completes, it's possible for an aborted connection to be returned to the pool.  The next time the connection is used, HttpClient.execute fails without retrying, throwing this exception:

java.io.IOException: Connection already shutdown
        at org.apache.http.impl.conn.DefaultClientConnection.opening(DefaultClientConnection.java:112)
        at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:120)
        at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:147)
        at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:101)
        at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:381)
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)

Steps to reproduce:
1) Set a breakpoint in ThreadSafeClientConnManager.releaseConnection just after "reusable" is set (and found to be true).
2) Run to the breakpoint in releaseConnection.
3) Call HttpUriRequest.abort.
4) Let releaseConnection complete.

When the connection is next used, the exception will be thrown.

Snippet from ThreadSafeClientConnManager:
    public void releaseConnection(ManagedClientConnection conn, long validDuration, TimeUnit timeUnit) {
                ...
            boolean reusable = hca.isMarkedReusable();
            if (log.isDebugEnabled()) {                             // breakpoint here
                if (reusable) {
                    log.debug("Released connection is reusable.");
                } else {
                    log.debug("Released connection is not reusable.");
                }
            }
            hca.detach();
            if (entry != null) {
                connectionPool.freeEntry(entry, reusable, validDuration, timeUnit);
            }
        }
    }


I think that AbstractClientConnAdapter should be modified as follows:

1) Add "released" flag:

    /** True if the connection has been released. */
    private boolean released;

2) Modify abortConnection:

    public void abortConnection() {
        synchronized(this) {
            if (aborted || released) {
                return;
            }
            aborted = true;
        }
        unmarkReusable(); // this line and all that follow unchanged

3) Modify releaseConnection:

    public void releaseConnection() {
        synchronized(this) {
            if (aborted || released) {
                return;
            }
            released = true;
        }
        if (connManager != null) {
            connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
        }
    }



--
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: dev-unsubscribe@...
For additional commands, e-mail: dev-help@...


[jira] Updated: (HTTPCLIENT-881) AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect

by JIRA jira@apache.org :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


     [ https://issues.apache.org/jira/browse/HTTPCLIENT-881?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Oleg Kalnichevski updated HTTPCLIENT-881:
-----------------------------------------

      Component/s:     (was: HttpClient)
                   HttpConn
         Priority: Major  (was: Minor)
    Fix Version/s: 4.1 Alpha1

Tim,

Would you be able to put all these changes in a patch (udiff format as produced by 'svn diff' command)?

Oleg

> AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect
> ---------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: HTTPCLIENT-881
>                 URL: https://issues.apache.org/jira/browse/HTTPCLIENT-881
>             Project: HttpComponents HttpClient
>          Issue Type: Bug
>          Components: HttpConn
>    Affects Versions: 4.0 Final
>            Reporter: Tim Boemker
>             Fix For: 4.1 Alpha1
>
>
> If HttpUriRequest.abort() is called at about the same time that the request completes, it's possible for an aborted connection to be returned to the pool.  The next time the connection is used, HttpClient.execute fails without retrying, throwing this exception:
> java.io.IOException: Connection already shutdown
> at org.apache.http.impl.conn.DefaultClientConnection.opening(DefaultClientConnection.java:112)
> at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:120)
> at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:147)
> at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:101)
> at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:381)
> at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
> at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)
> Steps to reproduce:
> 1) Set a breakpoint in ThreadSafeClientConnManager.releaseConnection just after "reusable" is set (and found to be true).
> 2) Run to the breakpoint in releaseConnection.
> 3) Call HttpUriRequest.abort.
> 4) Let releaseConnection complete.
> When the connection is next used, the exception will be thrown.
> Snippet from ThreadSafeClientConnManager:
>     public void releaseConnection(ManagedClientConnection conn, long validDuration, TimeUnit timeUnit) {
> ...
>             boolean reusable = hca.isMarkedReusable();
>             if (log.isDebugEnabled()) {                             // breakpoint here
>                 if (reusable) {
>                     log.debug("Released connection is reusable.");
>                 } else {
>                     log.debug("Released connection is not reusable.");
>                 }
>             }
>             hca.detach();
>             if (entry != null) {
>                 connectionPool.freeEntry(entry, reusable, validDuration, timeUnit);
>             }
>         }
>     }
> I think that AbstractClientConnAdapter should be modified as follows:
> 1) Add "released" flag:
>     /** True if the connection has been released. */
>     private boolean released;
> 2) Modify abortConnection:
>     public void abortConnection() {
>         synchronized(this) {
>             if (aborted || released) {
>                 return;
>             }
>             aborted = true;
>         }
>         unmarkReusable(); // this line and all that follow unchanged
> 3) Modify releaseConnection:
>     public void releaseConnection() {
>         synchronized(this) {
>             if (aborted || released) {
>                 return;
>             }
>             released = true;
>         }
>         if (connManager != null) {
>             connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
>         }
>     }

--
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: dev-unsubscribe@...
For additional commands, e-mail: dev-help@...


[jira] Updated: (HTTPCLIENT-881) AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect

by JIRA jira@apache.org :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


     [ https://issues.apache.org/jira/browse/HTTPCLIENT-881?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Tim Boemker updated HTTPCLIENT-881:
-----------------------------------

    Attachment: HTTPCLIENT-881.patch

Also attached.

Index: AbstractClientConnAdapter.java
===================================================================
--- AbstractClientConnAdapter.java      (revision 825665)
+++ AbstractClientConnAdapter.java      (working copy)
@@ -86,6 +86,9 @@
     /** True if the connection has been aborted. */
     private volatile boolean aborted;

+    /** True if the connection has been released. */
+    private boolean released;
+
     /** The duration this is valid for while idle (in ms). */
     private volatile long duration;

@@ -316,16 +319,25 @@
     }

     public void releaseConnection() {
+        synchronized(this) {
+            if (aborted || released) {
+                return;
+            }
+            released = true;
+        }
         if (connManager != null) {
             connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
         }
     }

+
     public void abortConnection() {
-        if (aborted) {
-            return;
+        synchronized(this) {
+            if (aborted || released) {
+                return;
+            }
+            aborted = true;
         }
-        aborted = true;
         unmarkReusable();
         try {
             shutdown();





> AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect
> ---------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: HTTPCLIENT-881
>                 URL: https://issues.apache.org/jira/browse/HTTPCLIENT-881
>             Project: HttpComponents HttpClient
>          Issue Type: Bug
>          Components: HttpConn
>    Affects Versions: 4.0 Final
>            Reporter: Tim Boemker
>             Fix For: 4.1 Alpha1
>
>         Attachments: HTTPCLIENT-881.patch
>
>
> If HttpUriRequest.abort() is called at about the same time that the request completes, it's possible for an aborted connection to be returned to the pool.  The next time the connection is used, HttpClient.execute fails without retrying, throwing this exception:
> java.io.IOException: Connection already shutdown
> at org.apache.http.impl.conn.DefaultClientConnection.opening(DefaultClientConnection.java:112)
> at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:120)
> at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:147)
> at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:101)
> at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:381)
> at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
> at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)
> Steps to reproduce:
> 1) Set a breakpoint in ThreadSafeClientConnManager.releaseConnection just after "reusable" is set (and found to be true).
> 2) Run to the breakpoint in releaseConnection.
> 3) Call HttpUriRequest.abort.
> 4) Let releaseConnection complete.
> When the connection is next used, the exception will be thrown.
> Snippet from ThreadSafeClientConnManager:
>     public void releaseConnection(ManagedClientConnection conn, long validDuration, TimeUnit timeUnit) {
> ...
>             boolean reusable = hca.isMarkedReusable();
>             if (log.isDebugEnabled()) {                             // breakpoint here
>                 if (reusable) {
>                     log.debug("Released connection is reusable.");
>                 } else {
>                     log.debug("Released connection is not reusable.");
>                 }
>             }
>             hca.detach();
>             if (entry != null) {
>                 connectionPool.freeEntry(entry, reusable, validDuration, timeUnit);
>             }
>         }
>     }
> I think that AbstractClientConnAdapter should be modified as follows:
> 1) Add "released" flag:
>     /** True if the connection has been released. */
>     private boolean released;
> 2) Modify abortConnection:
>     public void abortConnection() {
>         synchronized(this) {
>             if (aborted || released) {
>                 return;
>             }
>             aborted = true;
>         }
>         unmarkReusable(); // this line and all that follow unchanged
> 3) Modify releaseConnection:
>     public void releaseConnection() {
>         synchronized(this) {
>             if (aborted || released) {
>                 return;
>             }
>             released = true;
>         }
>         if (connManager != null) {
>             connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
>         }
>     }

--
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: dev-unsubscribe@...
For additional commands, e-mail: dev-help@...


[jira] Resolved: (HTTPCLIENT-881) AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect

by JIRA jira@apache.org :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


     [ https://issues.apache.org/jira/browse/HTTPCLIENT-881?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Oleg Kalnichevski resolved HTTPCLIENT-881.
------------------------------------------

    Resolution: Fixed

Tim

There was a regression in the test suite with your patch. I came up with a slight variation on your patch that appears to fix the race condition while preserving compatibility with the original behaviour of HttpUriRequest#abort(). Please pull the latest code from the SVN repository, review the changes an confirm the problem has been adequately fixed.

I did not investigate thoroughly why those test cases started to fail. It can well be the test cases are flawed somehow.

Oleg

----
Results :

Tests in error:
  testAbortDuringConnecting(org.apache.http.impl.conn.TestTSCCMWithServer)
  testAbortBeforeSocketCreate(org.apache.http.impl.conn.TestTSCCMWithServer)
  testAbortAfterSocketConnect(org.apache.http.impl.conn.TestTSCCMWithServer)
  testAbortAfterOperatorOpen(org.apache.http.impl.conn.TestTSCCMWithServer)

Tests run: 477, Failures: 0, Errors: 4, Skipped: 0
----

> AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect
> ---------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: HTTPCLIENT-881
>                 URL: https://issues.apache.org/jira/browse/HTTPCLIENT-881
>             Project: HttpComponents HttpClient
>          Issue Type: Bug
>          Components: HttpConn
>    Affects Versions: 4.0 Final
>            Reporter: Tim Boemker
>             Fix For: 4.1 Alpha1
>
>         Attachments: HTTPCLIENT-881.patch
>
>
> If HttpUriRequest.abort() is called at about the same time that the request completes, it's possible for an aborted connection to be returned to the pool.  The next time the connection is used, HttpClient.execute fails without retrying, throwing this exception:
> java.io.IOException: Connection already shutdown
> at org.apache.http.impl.conn.DefaultClientConnection.opening(DefaultClientConnection.java:112)
> at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:120)
> at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:147)
> at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:101)
> at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:381)
> at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
> at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)
> Steps to reproduce:
> 1) Set a breakpoint in ThreadSafeClientConnManager.releaseConnection just after "reusable" is set (and found to be true).
> 2) Run to the breakpoint in releaseConnection.
> 3) Call HttpUriRequest.abort.
> 4) Let releaseConnection complete.
> When the connection is next used, the exception will be thrown.
> Snippet from ThreadSafeClientConnManager:
>     public void releaseConnection(ManagedClientConnection conn, long validDuration, TimeUnit timeUnit) {
> ...
>             boolean reusable = hca.isMarkedReusable();
>             if (log.isDebugEnabled()) {                             // breakpoint here
>                 if (reusable) {
>                     log.debug("Released connection is reusable.");
>                 } else {
>                     log.debug("Released connection is not reusable.");
>                 }
>             }
>             hca.detach();
>             if (entry != null) {
>                 connectionPool.freeEntry(entry, reusable, validDuration, timeUnit);
>             }
>         }
>     }
> I think that AbstractClientConnAdapter should be modified as follows:
> 1) Add "released" flag:
>     /** True if the connection has been released. */
>     private boolean released;
> 2) Modify abortConnection:
>     public void abortConnection() {
>         synchronized(this) {
>             if (aborted || released) {
>                 return;
>             }
>             aborted = true;
>         }
>         unmarkReusable(); // this line and all that follow unchanged
> 3) Modify releaseConnection:
>     public void releaseConnection() {
>         synchronized(this) {
>             if (aborted || released) {
>                 return;
>             }
>             released = true;
>         }
>         if (connManager != null) {
>             connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
>         }
>     }

--
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: dev-unsubscribe@...
For additional commands, e-mail: dev-help@...


[jira] Commented: (HTTPCLIENT-881) AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect

by JIRA jira@apache.org :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


    [ https://issues.apache.org/jira/browse/HTTPCLIENT-881?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12766537#action_12766537 ]

Oleg Kalnichevski commented on HTTPCLIENT-881:
----------------------------------------------

I figured why the test cases were failing. It was due to an erroneous assumption that connection abort would not automatically release the connection back to the manager. I also removed an old ugly hack that was no longer relevant / valid.

All looks okay to me now. Double-check, nonetheless.

Oleg

> AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect
> ---------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: HTTPCLIENT-881
>                 URL: https://issues.apache.org/jira/browse/HTTPCLIENT-881
>             Project: HttpComponents HttpClient
>          Issue Type: Bug
>          Components: HttpConn
>    Affects Versions: 4.0 Final
>            Reporter: Tim Boemker
>             Fix For: 4.1 Alpha1
>
>         Attachments: HTTPCLIENT-881.patch
>
>
> If HttpUriRequest.abort() is called at about the same time that the request completes, it's possible for an aborted connection to be returned to the pool.  The next time the connection is used, HttpClient.execute fails without retrying, throwing this exception:
> java.io.IOException: Connection already shutdown
> at org.apache.http.impl.conn.DefaultClientConnection.opening(DefaultClientConnection.java:112)
> at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:120)
> at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:147)
> at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:101)
> at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:381)
> at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
> at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)
> Steps to reproduce:
> 1) Set a breakpoint in ThreadSafeClientConnManager.releaseConnection just after "reusable" is set (and found to be true).
> 2) Run to the breakpoint in releaseConnection.
> 3) Call HttpUriRequest.abort.
> 4) Let releaseConnection complete.
> When the connection is next used, the exception will be thrown.
> Snippet from ThreadSafeClientConnManager:
>     public void releaseConnection(ManagedClientConnection conn, long validDuration, TimeUnit timeUnit) {
> ...
>             boolean reusable = hca.isMarkedReusable();
>             if (log.isDebugEnabled()) {                             // breakpoint here
>                 if (reusable) {
>                     log.debug("Released connection is reusable.");
>                 } else {
>                     log.debug("Released connection is not reusable.");
>                 }
>             }
>             hca.detach();
>             if (entry != null) {
>                 connectionPool.freeEntry(entry, reusable, validDuration, timeUnit);
>             }
>         }
>     }
> I think that AbstractClientConnAdapter should be modified as follows:
> 1) Add "released" flag:
>     /** True if the connection has been released. */
>     private boolean released;
> 2) Modify abortConnection:
>     public void abortConnection() {
>         synchronized(this) {
>             if (aborted || released) {
>                 return;
>             }
>             aborted = true;
>         }
>         unmarkReusable(); // this line and all that follow unchanged
> 3) Modify releaseConnection:
>     public void releaseConnection() {
>         synchronized(this) {
>             if (aborted || released) {
>                 return;
>             }
>             released = true;
>         }
>         if (connManager != null) {
>             connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
>         }
>     }

--
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: dev-unsubscribe@...
For additional commands, e-mail: dev-help@...


[jira] Commented: (HTTPCLIENT-881) AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect

by JIRA jira@apache.org :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


    [ https://issues.apache.org/jira/browse/HTTPCLIENT-881?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12766560#action_12766560 ]

Tim Boemker commented on HTTPCLIENT-881:
----------------------------------------

The current version of the code still has a race condition.  In AbstractClientConnection.java, it's possible for abortConnection and releaseConnection both to read shutdown as false and for both to continue execution.  ThreadSafeClientConnManager.releaseConnection is not thread-safe when two threads are trying to release the same connection.

I am following these steps to demonstrate the race condition:
1) Let abortConnection and releaseConnection both step through the line that tests whether shutdown is already set.
2) Let the thread running releaseConnection run just past the line in ThreadSafeClientConnManager.releaseConnection that sets local variable reusable from hca.isMarkedReusable.
3) Let the thread running abortConnection run to the same point.
4) Let the thread running releaseConnection finish.
5) Let the thread running abortConnection finish.
6) Attempt another request to the same host.

These steps consistently produce the following error:
java.lang.IllegalStateException: There is no entry that could be dropped.
        at org.apache.http.impl.conn.tsccm.RouteSpecificPool.dropEntry(RouteSpecificPool.java:244)
        at org.apache.http.impl.conn.tsccm.ConnPoolByRoute.freeEntry(ConnPoolByRoute.java:418)
        at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager.releaseConnection(ThreadSafeClientConnManager.java:254)
        at org.apache.http.impl.conn.AbstractClientConnAdapter.abortConnection(AbstractClientConnAdapter.java:338)
        at org.apache.http.impl.client.DefaultRequestDirector.abortConnection(DefaultRequestDirector.java:1058)
        at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:566)
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:674)
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:609)
        ...

I propose the following change to the current version of AbstractClientConnection.java:

Index: AbstractClientConnAdapter.java
===================================================================
--- AbstractClientConnAdapter.java      (revision 825909)
+++ AbstractClientConnAdapter.java      (working copy)
@@ -311,20 +311,24 @@
     }

     public void releaseConnection() {
-        if (shutdown) {
-            return;
+        synchronized(this) {
+            if (shutdown) {
+                return;
+            }
+            shutdown = true;
         }
-        shutdown = true;
         if (connManager != null) {
             connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
         }
     }

     public void abortConnection() {
-        if (shutdown) {
-            return;
+        synchronized(this) {
+            if (shutdown) {
+                return;
+            }
+            shutdown = true;
         }
-        shutdown = true;
         unmarkReusable();
         try {
             shutdown();

With this code change, the regression tests pass and, I think, the problem is fixed.

> AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect
> ---------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: HTTPCLIENT-881
>                 URL: https://issues.apache.org/jira/browse/HTTPCLIENT-881
>             Project: HttpComponents HttpClient
>          Issue Type: Bug
>          Components: HttpConn
>    Affects Versions: 4.0 Final
>            Reporter: Tim Boemker
>             Fix For: 4.1 Alpha1
>
>         Attachments: HTTPCLIENT-881.patch
>
>
> If HttpUriRequest.abort() is called at about the same time that the request completes, it's possible for an aborted connection to be returned to the pool.  The next time the connection is used, HttpClient.execute fails without retrying, throwing this exception:
> java.io.IOException: Connection already shutdown
> at org.apache.http.impl.conn.DefaultClientConnection.opening(DefaultClientConnection.java:112)
> at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:120)
> at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:147)
> at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:101)
> at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:381)
> at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
> at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)
> Steps to reproduce:
> 1) Set a breakpoint in ThreadSafeClientConnManager.releaseConnection just after "reusable" is set (and found to be true).
> 2) Run to the breakpoint in releaseConnection.
> 3) Call HttpUriRequest.abort.
> 4) Let releaseConnection complete.
> When the connection is next used, the exception will be thrown.
> Snippet from ThreadSafeClientConnManager:
>     public void releaseConnection(ManagedClientConnection conn, long validDuration, TimeUnit timeUnit) {
> ...
>             boolean reusable = hca.isMarkedReusable();
>             if (log.isDebugEnabled()) {                             // breakpoint here
>                 if (reusable) {
>                     log.debug("Released connection is reusable.");
>                 } else {
>                     log.debug("Released connection is not reusable.");
>                 }
>             }
>             hca.detach();
>             if (entry != null) {
>                 connectionPool.freeEntry(entry, reusable, validDuration, timeUnit);
>             }
>         }
>     }
> I think that AbstractClientConnAdapter should be modified as follows:
> 1) Add "released" flag:
>     /** True if the connection has been released. */
>     private boolean released;
> 2) Modify abortConnection:
>     public void abortConnection() {
>         synchronized(this) {
>             if (aborted || released) {
>                 return;
>             }
>             aborted = true;
>         }
>         unmarkReusable(); // this line and all that follow unchanged
> 3) Modify releaseConnection:
>     public void releaseConnection() {
>         synchronized(this) {
>             if (aborted || released) {
>                 return;
>             }
>             released = true;
>         }
>         if (connManager != null) {
>             connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
>         }
>     }

--
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: dev-unsubscribe@...
For additional commands, e-mail: dev-help@...


[jira] Commented: (HTTPCLIENT-881) AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect

by JIRA jira@apache.org :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


    [ https://issues.apache.org/jira/browse/HTTPCLIENT-881?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12766599#action_12766599 ]

Oleg Kalnichevski commented on HTTPCLIENT-881:
----------------------------------------------

* Methods mutating the internal state of the AbstractClientConnAdapter class and its subclasses made synchronized
* ThreadSafeClientConnManager#releaseConnection method now synchronizes access to the BasicPooledConnAdapter instance

Please review / re-test

Oleg

> AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect
> ---------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: HTTPCLIENT-881
>                 URL: https://issues.apache.org/jira/browse/HTTPCLIENT-881
>             Project: HttpComponents HttpClient
>          Issue Type: Bug
>          Components: HttpConn
>    Affects Versions: 4.0 Final
>            Reporter: Tim Boemker
>             Fix For: 4.1 Alpha1
>
>         Attachments: HTTPCLIENT-881.patch
>
>
> If HttpUriRequest.abort() is called at about the same time that the request completes, it's possible for an aborted connection to be returned to the pool.  The next time the connection is used, HttpClient.execute fails without retrying, throwing this exception:
> java.io.IOException: Connection already shutdown
> at org.apache.http.impl.conn.DefaultClientConnection.opening(DefaultClientConnection.java:112)
> at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:120)
> at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:147)
> at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:101)
> at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:381)
> at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
> at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)
> Steps to reproduce:
> 1) Set a breakpoint in ThreadSafeClientConnManager.releaseConnection just after "reusable" is set (and found to be true).
> 2) Run to the breakpoint in releaseConnection.
> 3) Call HttpUriRequest.abort.
> 4) Let releaseConnection complete.
> When the connection is next used, the exception will be thrown.
> Snippet from ThreadSafeClientConnManager:
>     public void releaseConnection(ManagedClientConnection conn, long validDuration, TimeUnit timeUnit) {
> ...
>             boolean reusable = hca.isMarkedReusable();
>             if (log.isDebugEnabled()) {                             // breakpoint here
>                 if (reusable) {
>                     log.debug("Released connection is reusable.");
>                 } else {
>                     log.debug("Released connection is not reusable.");
>                 }
>             }
>             hca.detach();
>             if (entry != null) {
>                 connectionPool.freeEntry(entry, reusable, validDuration, timeUnit);
>             }
>         }
>     }
> I think that AbstractClientConnAdapter should be modified as follows:
> 1) Add "released" flag:
>     /** True if the connection has been released. */
>     private boolean released;
> 2) Modify abortConnection:
>     public void abortConnection() {
>         synchronized(this) {
>             if (aborted || released) {
>                 return;
>             }
>             aborted = true;
>         }
>         unmarkReusable(); // this line and all that follow unchanged
> 3) Modify releaseConnection:
>     public void releaseConnection() {
>         synchronized(this) {
>             if (aborted || released) {
>                 return;
>             }
>             released = true;
>         }
>         if (connManager != null) {
>             connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
>         }
>     }

--
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: dev-unsubscribe@...
For additional commands, e-mail: dev-help@...


[jira] Commented: (HTTPCLIENT-881) AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect

by JIRA jira@apache.org :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


    [ https://issues.apache.org/jira/browse/HTTPCLIENT-881?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12766630#action_12766630 ]

Tim Boemker commented on HTTPCLIENT-881:
----------------------------------------

With the latest changes, I'm able to get HttpClient.execute to throw an IllegalStateException.

Steps to reproduce:

1) Run one thread to line 385 in DefaultRequestDirector, where it calls establishRoute.
2) Run a second thread that calls HttpUriRequest.abort.  Abort calls BasicPooledConnAdapter.abortConnection, which calls ThreadSafeClientConnManager.releaseConnection, which calls BasicPooledConnAdapter.detach.
3) Let the main thread continue. It throws an IllegalStateException because the adapter is now detached:

java.lang.IllegalStateException: Adapter is detached.
        at org.apache.http.impl.conn.AbstractPooledConnAdapter.assertAttached(AbstractPooledConnAdapter.java:75)
        at org.apache.http.impl.conn.AbstractPooledConnAdapter.getRoute(AbstractPooledConnAdapter.java:91)
        at org.apache.http.impl.client.DefaultRequestDirector.establishRoute(DefaultRequestDirector.java:641)
        at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:385)
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:674)
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:609)

> AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect
> ---------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: HTTPCLIENT-881
>                 URL: https://issues.apache.org/jira/browse/HTTPCLIENT-881
>             Project: HttpComponents HttpClient
>          Issue Type: Bug
>          Components: HttpConn
>    Affects Versions: 4.0 Final
>            Reporter: Tim Boemker
>             Fix For: 4.1 Alpha1
>
>         Attachments: HTTPCLIENT-881.patch
>
>
> If HttpUriRequest.abort() is called at about the same time that the request completes, it's possible for an aborted connection to be returned to the pool.  The next time the connection is used, HttpClient.execute fails without retrying, throwing this exception:
> java.io.IOException: Connection already shutdown
> at org.apache.http.impl.conn.DefaultClientConnection.opening(DefaultClientConnection.java:112)
> at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:120)
> at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:147)
> at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:101)
> at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:381)
> at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
> at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)
> Steps to reproduce:
> 1) Set a breakpoint in ThreadSafeClientConnManager.releaseConnection just after "reusable" is set (and found to be true).
> 2) Run to the breakpoint in releaseConnection.
> 3) Call HttpUriRequest.abort.
> 4) Let releaseConnection complete.
> When the connection is next used, the exception will be thrown.
> Snippet from ThreadSafeClientConnManager:
>     public void releaseConnection(ManagedClientConnection conn, long validDuration, TimeUnit timeUnit) {
> ...
>             boolean reusable = hca.isMarkedReusable();
>             if (log.isDebugEnabled()) {                             // breakpoint here
>                 if (reusable) {
>                     log.debug("Released connection is reusable.");
>                 } else {
>                     log.debug("Released connection is not reusable.");
>                 }
>             }
>             hca.detach();
>             if (entry != null) {
>                 connectionPool.freeEntry(entry, reusable, validDuration, timeUnit);
>             }
>         }
>     }
> I think that AbstractClientConnAdapter should be modified as follows:
> 1) Add "released" flag:
>     /** True if the connection has been released. */
>     private boolean released;
> 2) Modify abortConnection:
>     public void abortConnection() {
>         synchronized(this) {
>             if (aborted || released) {
>                 return;
>             }
>             aborted = true;
>         }
>         unmarkReusable(); // this line and all that follow unchanged
> 3) Modify releaseConnection:
>     public void releaseConnection() {
>         synchronized(this) {
>             if (aborted || released) {
>                 return;
>             }
>             released = true;
>         }
>         if (connManager != null) {
>             connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
>         }
>     }

--
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: dev-unsubscribe@...
For additional commands, e-mail: dev-help@...


[jira] Commented: (HTTPCLIENT-881) AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect

by JIRA jira@apache.org :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


    [ https://issues.apache.org/jira/browse/HTTPCLIENT-881?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12766636#action_12766636 ]

Tim Boemker commented on HTTPCLIENT-881:
----------------------------------------

I see that the code in AbstractClientConnAdapter.abortConnection was changed from this:

        // Usually #abortConnection() is expected to be called from
        // a helper thread in order to unblock the main execution thread
        // blocked in an I/O operation. It may be unsafe to call
        // #releaseConnection() from the helper thread, so we have to rely
        // on an IOException thrown by the closed socket on the main thread
        // to trigger the release of the connection back to the
        // connection manager.
        //
        // However, if this method is called from the main execution thread
        // it should be safe to release the connection immediately. Besides,
        // this also helps ensure the connection gets released back to the
        // manager if #abortConnection() is called from the main execution
        // thread while there is no blocking I/O operation.
        if (executionThread.equals(Thread.currentThread())) {
            releaseConnection();
        }

to this:

        if (connManager != null) {
            connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
        }

Perhaps the comment in the original code was correct.

> AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect
> ---------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: HTTPCLIENT-881
>                 URL: https://issues.apache.org/jira/browse/HTTPCLIENT-881
>             Project: HttpComponents HttpClient
>          Issue Type: Bug
>          Components: HttpConn
>    Affects Versions: 4.0 Final
>            Reporter: Tim Boemker
>             Fix For: 4.1 Alpha1
>
>         Attachments: HTTPCLIENT-881.patch
>
>
> If HttpUriRequest.abort() is called at about the same time that the request completes, it's possible for an aborted connection to be returned to the pool.  The next time the connection is used, HttpClient.execute fails without retrying, throwing this exception:
> java.io.IOException: Connection already shutdown
> at org.apache.http.impl.conn.DefaultClientConnection.opening(DefaultClientConnection.java:112)
> at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:120)
> at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:147)
> at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:101)
> at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:381)
> at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
> at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)
> Steps to reproduce:
> 1) Set a breakpoint in ThreadSafeClientConnManager.releaseConnection just after "reusable" is set (and found to be true).
> 2) Run to the breakpoint in releaseConnection.
> 3) Call HttpUriRequest.abort.
> 4) Let releaseConnection complete.
> When the connection is next used, the exception will be thrown.
> Snippet from ThreadSafeClientConnManager:
>     public void releaseConnection(ManagedClientConnection conn, long validDuration, TimeUnit timeUnit) {
> ...
>             boolean reusable = hca.isMarkedReusable();
>             if (log.isDebugEnabled()) {                             // breakpoint here
>                 if (reusable) {
>                     log.debug("Released connection is reusable.");
>                 } else {
>                     log.debug("Released connection is not reusable.");
>                 }
>             }
>             hca.detach();
>             if (entry != null) {
>                 connectionPool.freeEntry(entry, reusable, validDuration, timeUnit);
>             }
>         }
>     }
> I think that AbstractClientConnAdapter should be modified as follows:
> 1) Add "released" flag:
>     /** True if the connection has been released. */
>     private boolean released;
> 2) Modify abortConnection:
>     public void abortConnection() {
>         synchronized(this) {
>             if (aborted || released) {
>                 return;
>             }
>             aborted = true;
>         }
>         unmarkReusable(); // this line and all that follow unchanged
> 3) Modify releaseConnection:
>     public void releaseConnection() {
>         synchronized(this) {
>             if (aborted || released) {
>                 return;
>             }
>             released = true;
>         }
>         if (connManager != null) {
>             connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
>         }
>     }

--
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: dev-unsubscribe@...
For additional commands, e-mail: dev-help@...


[jira] Commented: (HTTPCLIENT-881) AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect

by JIRA jira@apache.org :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


    [ https://issues.apache.org/jira/browse/HTTPCLIENT-881?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12766663#action_12766663 ]

Oleg Kalnichevski commented on HTTPCLIENT-881:
----------------------------------------------

I think it is perfectly reasonable that an attempt to perform an operation on an aborted connection would cause an exception of some sort. I made sure, though, that a normal operation (such as I/O operation) would result in an InterruptedIOException not IllegalStateException.

Please re-test

Oleg

> AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect
> ---------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: HTTPCLIENT-881
>                 URL: https://issues.apache.org/jira/browse/HTTPCLIENT-881
>             Project: HttpComponents HttpClient
>          Issue Type: Bug
>          Components: HttpConn
>    Affects Versions: 4.0 Final
>            Reporter: Tim Boemker
>             Fix For: 4.1 Alpha1
>
>         Attachments: HTTPCLIENT-881.patch
>
>
> If HttpUriRequest.abort() is called at about the same time that the request completes, it's possible for an aborted connection to be returned to the pool.  The next time the connection is used, HttpClient.execute fails without retrying, throwing this exception:
> java.io.IOException: Connection already shutdown
> at org.apache.http.impl.conn.DefaultClientConnection.opening(DefaultClientConnection.java:112)
> at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:120)
> at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:147)
> at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:101)
> at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:381)
> at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
> at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)
> Steps to reproduce:
> 1) Set a breakpoint in ThreadSafeClientConnManager.releaseConnection just after "reusable" is set (and found to be true).
> 2) Run to the breakpoint in releaseConnection.
> 3) Call HttpUriRequest.abort.
> 4) Let releaseConnection complete.
> When the connection is next used, the exception will be thrown.
> Snippet from ThreadSafeClientConnManager:
>     public void releaseConnection(ManagedClientConnection conn, long validDuration, TimeUnit timeUnit) {
> ...
>             boolean reusable = hca.isMarkedReusable();
>             if (log.isDebugEnabled()) {                             // breakpoint here
>                 if (reusable) {
>                     log.debug("Released connection is reusable.");
>                 } else {
>                     log.debug("Released connection is not reusable.");
>                 }
>             }
>             hca.detach();
>             if (entry != null) {
>                 connectionPool.freeEntry(entry, reusable, validDuration, timeUnit);
>             }
>         }
>     }
> I think that AbstractClientConnAdapter should be modified as follows:
> 1) Add "released" flag:
>     /** True if the connection has been released. */
>     private boolean released;
> 2) Modify abortConnection:
>     public void abortConnection() {
>         synchronized(this) {
>             if (aborted || released) {
>                 return;
>             }
>             aborted = true;
>         }
>         unmarkReusable(); // this line and all that follow unchanged
> 3) Modify releaseConnection:
>     public void releaseConnection() {
>         synchronized(this) {
>             if (aborted || released) {
>                 return;
>             }
>             released = true;
>         }
>         if (connManager != null) {
>             connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
>         }
>     }

--
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: dev-unsubscribe@...
For additional commands, e-mail: dev-help@...


[jira] Commented: (HTTPCLIENT-881) AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect

by JIRA jira@apache.org :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


    [ https://issues.apache.org/jira/browse/HTTPCLIENT-881?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12766683#action_12766683 ]

Tim Boemker commented on HTTPCLIENT-881:
----------------------------------------

I did not find a defect in the new code.

> AbstractClientConnAdapter doesn't ensure that only one of ConnectionReleaseTrigger.abortConnection, .releaseConnection has effect
> ---------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: HTTPCLIENT-881
>                 URL: https://issues.apache.org/jira/browse/HTTPCLIENT-881
>             Project: HttpComponents HttpClient
>          Issue Type: Bug
>          Components: HttpConn
>    Affects Versions: 4.0 Final
>            Reporter: Tim Boemker
>             Fix For: 4.1 Alpha1
>
>         Attachments: HTTPCLIENT-881.patch
>
>
> If HttpUriRequest.abort() is called at about the same time that the request completes, it's possible for an aborted connection to be returned to the pool.  The next time the connection is used, HttpClient.execute fails without retrying, throwing this exception:
> java.io.IOException: Connection already shutdown
> at org.apache.http.impl.conn.DefaultClientConnection.opening(DefaultClientConnection.java:112)
> at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:120)
> at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:147)
> at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:101)
> at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:381)
> at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
> at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)
> Steps to reproduce:
> 1) Set a breakpoint in ThreadSafeClientConnManager.releaseConnection just after "reusable" is set (and found to be true).
> 2) Run to the breakpoint in releaseConnection.
> 3) Call HttpUriRequest.abort.
> 4) Let releaseConnection complete.
> When the connection is next used, the exception will be thrown.
> Snippet from ThreadSafeClientConnManager:
>     public void releaseConnection(ManagedClientConnection conn, long validDuration, TimeUnit timeUnit) {
> ...
>             boolean reusable = hca.isMarkedReusable();
>             if (log.isDebugEnabled()) {                             // breakpoint here
>                 if (reusable) {
>                     log.debug("Released connection is reusable.");
>                 } else {
>                     log.debug("Released connection is not reusable.");
>                 }
>             }
>             hca.detach();
>             if (entry != null) {
>                 connectionPool.freeEntry(entry, reusable, validDuration, timeUnit);
>             }
>         }
>     }
> I think that AbstractClientConnAdapter should be modified as follows:
> 1) Add "released" flag:
>     /** True if the connection has been released. */
>     private boolean released;
> 2) Modify abortConnection:
>     public void abortConnection() {
>         synchronized(this) {
>             if (aborted || released) {
>                 return;
>             }
>             aborted = true;
>         }
>         unmarkReusable(); // this line and all that follow unchanged
> 3) Modify releaseConnection:
>     public void releaseConnection() {
>         synchronized(this) {
>             if (aborted || released) {
>                 return;
>             }
>             released = true;
>         }
>         if (connManager != null) {
>             connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
>         }
>     }

--
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: dev-unsubscribe@...
For additional commands, e-mail: dev-help@...