HTTPCLIENT-881: Fixed race condition in AbstractClientConnAdapter that makes it possible for an aborted connection to be returned to the pool
Contributed by Tim Boemker <tboemker at elynx.com> git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@825864 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
0b815c2505
commit
4b422e1733
|
@ -1,6 +1,11 @@
|
||||||
Changes since 4.0
|
Changes since 4.0
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
* [HTTPCLIENT-881] Fixed race condition in AbstractClientConnAdapter that makes it
|
||||||
|
possible for an aborted connection to be returned to the pool.
|
||||||
|
Contributed by Tim Boemker <tboemker at elynx.com> and
|
||||||
|
Oleg Kalnichevski <olegk at apache.org>
|
||||||
|
|
||||||
* [HTTPCLIENT-832] Distinguish cookie format errors from violations of restrictions
|
* [HTTPCLIENT-832] Distinguish cookie format errors from violations of restrictions
|
||||||
imposed by a cookie specification. In the latter case
|
imposed by a cookie specification. In the latter case
|
||||||
CookieRestrictionViolationException will be thrown.
|
CookieRestrictionViolationException will be thrown.
|
||||||
|
|
|
@ -83,8 +83,8 @@ public abstract class AbstractClientConnAdapter implements ManagedClientConnecti
|
||||||
/** The reusability marker. */
|
/** The reusability marker. */
|
||||||
private volatile boolean markedReusable;
|
private volatile boolean markedReusable;
|
||||||
|
|
||||||
/** True if the connection has been aborted. */
|
/** True if the connection has been shut down or released. */
|
||||||
private volatile boolean aborted;
|
private volatile boolean shutdown;
|
||||||
|
|
||||||
/** The duration this is valid for while idle (in ms). */
|
/** The duration this is valid for while idle (in ms). */
|
||||||
private volatile long duration;
|
private volatile long duration;
|
||||||
|
@ -104,7 +104,7 @@ public abstract class AbstractClientConnAdapter implements ManagedClientConnecti
|
||||||
connManager = mgr;
|
connManager = mgr;
|
||||||
wrappedConnection = conn;
|
wrappedConnection = conn;
|
||||||
markedReusable = false;
|
markedReusable = false;
|
||||||
aborted = false;
|
shutdown = false;
|
||||||
duration = Long.MAX_VALUE;
|
duration = Long.MAX_VALUE;
|
||||||
} // <constructor>
|
} // <constructor>
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ public abstract class AbstractClientConnAdapter implements ManagedClientConnecti
|
||||||
* @throws InterruptedIOException if the connection has been aborted
|
* @throws InterruptedIOException if the connection has been aborted
|
||||||
*/
|
*/
|
||||||
protected final void assertNotAborted() throws InterruptedIOException {
|
protected final void assertNotAborted() throws InterruptedIOException {
|
||||||
if (aborted) {
|
if (shutdown) {
|
||||||
throw new InterruptedIOException("Connection has been shut down.");
|
throw new InterruptedIOException("Connection has been shut down.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,7 +160,7 @@ public abstract class AbstractClientConnAdapter implements ManagedClientConnecti
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isStale() {
|
public boolean isStale() {
|
||||||
if (aborted)
|
if (shutdown)
|
||||||
return true;
|
return true;
|
||||||
OperatedClientConnection conn = getWrappedConnection();
|
OperatedClientConnection conn = getWrappedConnection();
|
||||||
if (conn == null)
|
if (conn == null)
|
||||||
|
@ -316,16 +316,17 @@ public abstract class AbstractClientConnAdapter implements ManagedClientConnecti
|
||||||
}
|
}
|
||||||
|
|
||||||
public void releaseConnection() {
|
public void releaseConnection() {
|
||||||
|
shutdown = true;
|
||||||
if (connManager != null) {
|
if (connManager != null) {
|
||||||
connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
|
connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void abortConnection() {
|
public void abortConnection() {
|
||||||
if (aborted) {
|
if (shutdown) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
aborted = true;
|
shutdown = true;
|
||||||
unmarkReusable();
|
unmarkReusable();
|
||||||
try {
|
try {
|
||||||
shutdown();
|
shutdown();
|
||||||
|
@ -345,7 +346,9 @@ public abstract class AbstractClientConnAdapter implements ManagedClientConnecti
|
||||||
// manager if #abortConnection() is called from the main execution
|
// manager if #abortConnection() is called from the main execution
|
||||||
// thread while there is no blocking I/O operation.
|
// thread while there is no blocking I/O operation.
|
||||||
if (executionThread.equals(Thread.currentThread())) {
|
if (executionThread.equals(Thread.currentThread())) {
|
||||||
releaseConnection();
|
if (connManager != null) {
|
||||||
|
connManager.releaseConnection(this, duration, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue