Skip to content

Commit 2f6694f

Browse files
committed
Improved internal state representation of the internal async execution runtime in order to present potential race conditions
1 parent ff87bf0 commit 2f6694f

1 file changed

Lines changed: 20 additions & 15 deletions

File tree

httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttpAsyncExecRuntime.java

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,18 @@
5454

5555
class InternalHttpAsyncExecRuntime implements AsyncExecRuntime {
5656

57+
static class ReUseData {
58+
59+
final Object state;
60+
final TimeValue validDuration;
61+
62+
ReUseData(final Object state, final TimeValue validDuration) {
63+
this.state = state;
64+
this.validDuration = validDuration;
65+
}
66+
67+
}
68+
5769
private final Logger log;
5870
private final AsyncClientConnectionManager manager;
5971
private final ConnectionInitiator connectionInitiator;
@@ -64,9 +76,7 @@ class InternalHttpAsyncExecRuntime implements AsyncExecRuntime {
6476
@Deprecated
6577
private final TlsConfig tlsConfig;
6678
private final AtomicReference<AsyncConnectionEndpoint> endpointRef;
67-
private volatile boolean reusable;
68-
private volatile Object state;
69-
private volatile TimeValue validDuration;
79+
private final AtomicReference<ReUseData> reuseDataRef;
7080

7181
InternalHttpAsyncExecRuntime(
7282
final Logger log,
@@ -81,7 +91,7 @@ class InternalHttpAsyncExecRuntime implements AsyncExecRuntime {
8191
this.pushHandlerFactory = pushHandlerFactory;
8292
this.tlsConfig = tlsConfig;
8393
this.endpointRef = new AtomicReference<>();
84-
this.validDuration = TimeValue.NEG_ONE_MILLISECOND;
94+
this.reuseDataRef = new AtomicReference<>();
8595
}
8696

8797
@Override
@@ -97,7 +107,6 @@ public Cancellable acquireEndpoint(
97107
final HttpClientContext context,
98108
final FutureCallback<AsyncExecRuntime> callback) {
99109
if (endpointRef.get() == null) {
100-
state = object;
101110
final RequestConfig requestConfig = context.getRequestConfigOrDefault();
102111
final Timeout connectionRequestTimeout = requestConfig.getConnectionRequestTimeout();
103112
if (log.isDebugEnabled()) {
@@ -113,7 +122,6 @@ public Cancellable acquireEndpoint(
113122
@Override
114123
public void completed(final AsyncConnectionEndpoint connectionEndpoint) {
115124
endpointRef.set(connectionEndpoint);
116-
reusable = connectionEndpoint.isConnected();
117125
if (log.isDebugEnabled()) {
118126
log.debug("{} acquired endpoint {}", id, ConnPoolSupport.getId(connectionEndpoint));
119127
}
@@ -153,11 +161,12 @@ private void discardEndpoint(final AsyncConnectionEndpoint endpoint) {
153161
public void releaseEndpoint() {
154162
final AsyncConnectionEndpoint endpoint = endpointRef.getAndSet(null);
155163
if (endpoint != null) {
156-
if (reusable) {
164+
final ReUseData reUseData = reuseDataRef.getAndSet(null);
165+
if (reUseData != null) {
157166
if (log.isDebugEnabled()) {
158167
log.debug("{} releasing valid endpoint", ConnPoolSupport.getId(endpoint));
159168
}
160-
manager.release(endpoint, state, validDuration);
169+
manager.release(endpoint, reUseData.state, reUseData.validDuration);
161170
} else {
162171
discardEndpoint(endpoint);
163172
}
@@ -174,7 +183,7 @@ public void discardEndpoint() {
174183

175184
@Override
176185
public boolean validateConnection() {
177-
if (reusable) {
186+
if (reuseDataRef != null) {
178187
final AsyncConnectionEndpoint endpoint = endpointRef.get();
179188
return endpoint != null && endpoint.isConnected();
180189
}
@@ -325,16 +334,12 @@ public void cancelled() {
325334

326335
@Override
327336
public void markConnectionReusable(final Object newState, final TimeValue newValidDuration) {
328-
reusable = true;
329-
state = newState;
330-
validDuration = newValidDuration;
337+
reuseDataRef.set(new ReUseData(newState, newValidDuration));
331338
}
332339

333340
@Override
334341
public void markConnectionNonReusable() {
335-
reusable = false;
336-
state = null;
337-
validDuration = null;
342+
reuseDataRef.set(null);
338343
}
339344

340345
@Override

0 commit comments

Comments
 (0)