Skip to content

Commit 104865d

Browse files
author
Stephane Landelle
committed
Possible event loss when pooled connection is closed before writing, close AsyncHttpClient#768
1 parent afd3068 commit 104865d

File tree

2 files changed

+36
-26
lines changed

2 files changed

+36
-26
lines changed

src/main/java/com/ning/http/client/providers/netty/handler/Processor.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import com.ning.http.client.providers.netty.future.NettyResponseFuture;
3333
import com.ning.http.client.providers.netty.future.StackTraceInspector;
3434
import com.ning.http.client.providers.netty.request.NettyRequestSender;
35-
import com.ning.http.util.AsyncHttpProviderUtils;
3635

3736
import java.io.IOException;
3837
import java.nio.channels.ClosedChannelException;
@@ -128,12 +127,7 @@ public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws
128127
return;
129128

130129
protocol.onClose(future);
131-
132-
if (future.isDone())
133-
channelManager.closeChannel(channel);
134-
135-
else if (!requestSender.retry(future))
136-
requestSender.abort(channel, future, AsyncHttpProviderUtils.REMOTELY_CLOSED_EXCEPTION);
130+
requestSender.handleUnexpectedClosedChannel(channel, future);
137131
}
138132
}
139133

src/main/java/com/ning/http/client/providers/netty/request/NettyRequestSender.java

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import static com.ning.http.client.providers.netty.util.HttpUtils.useProxyConnect;
1818
import static com.ning.http.util.AsyncHttpProviderUtils.getDefaultPort;
1919
import static com.ning.http.util.AsyncHttpProviderUtils.requestTimeout;
20+
import static com.ning.http.util.AsyncHttpProviderUtils.REMOTELY_CLOSED_EXCEPTION;
2021
import static com.ning.http.util.ProxyUtils.avoidProxy;
2122
import static com.ning.http.util.ProxyUtils.getProxyServer;
2223

@@ -207,28 +208,35 @@ private <T> ListenableFuture<T> sendRequestWithCachedChannel(Request request, Ur
207208
future.attachChannel(channel, false);
208209

209210
LOGGER.debug("Using cached Channel {}\n for request \n{}\n", channel, future.getNettyRequest().getHttpRequest());
210-
Channels.setAttribute(channel, future);
211211

212-
try {
213-
writeRequest(future, channel);
214-
} catch (Exception ex) {
215-
// write request isn't supposed to throw Exceptions
216-
LOGGER.debug("writeRequest failure", ex);
217-
if (ex.getMessage() != null && ex.getMessage().contains("SSLEngine")) {
218-
// FIXME what is this for? https://github.com/AsyncHttpClient/async-http-client/commit/a847c3d4523ccc09827743e15b17e6bab59c553b
219-
// can such an exception happen as we write async?
220-
LOGGER.debug("SSLEngine failure", ex);
221-
future = null;
222-
} else {
223-
try {
224-
asyncHandler.onThrowable(ex);
225-
} catch (Throwable t) {
226-
LOGGER.warn("doConnect.writeRequest()", t);
212+
if (Channels.isChannelValid(channel)) {
213+
Channels.setAttribute(channel, future);
214+
215+
try {
216+
writeRequest(future, channel);
217+
} catch (Exception ex) {
218+
// write request isn't supposed to throw Exceptions
219+
LOGGER.debug("writeRequest failure", ex);
220+
if (ex.getMessage() != null && ex.getMessage().contains("SSLEngine")) {
221+
// FIXME what is this for? https://github.com/AsyncHttpClient/async-http-client/commit/a847c3d4523ccc09827743e15b17e6bab59c553b
222+
// can such an exception happen as we write async?
223+
LOGGER.debug("SSLEngine failure", ex);
224+
future = null;
225+
} else {
226+
try {
227+
asyncHandler.onThrowable(ex);
228+
} catch (Throwable t) {
229+
LOGGER.warn("doConnect.writeRequest()", t);
230+
}
231+
IOException ioe = new IOException(ex.getMessage());
232+
ioe.initCause(ex);
233+
throw ioe;
227234
}
228-
IOException ioe = new IOException(ex.getMessage());
229-
ioe.initCause(ex);
230-
throw ioe;
231235
}
236+
} else {
237+
// bad luck, the channel was closed in-between
238+
// there's a very good chance onClose was already notified but the future wasn't already registered
239+
handleUnexpectedClosedChannel(channel, future);
232240
}
233241
return future;
234242
}
@@ -413,6 +421,14 @@ public void abort(Channel channel, NettyResponseFuture<?> future, Throwable t) {
413421
}
414422
}
415423

424+
public void handleUnexpectedClosedChannel(Channel channel, NettyResponseFuture<?> future) {
425+
if (future.isDone())
426+
channelManager.closeChannel(channel);
427+
428+
else if (!retry(future))
429+
abort(channel, future, REMOTELY_CLOSED_EXCEPTION);
430+
}
431+
416432
public boolean retry(NettyResponseFuture<?> future) {
417433

418434
if (isClosed())

0 commit comments

Comments
 (0)