Skip to content

Commit adb42e0

Browse files
committed
Update FeedableBodyGenerator to prevent feed logic execution from blocking the selector thread by checking if the current thread is the selector thread and if true, execute the task on a worker thread.
1 parent 2846817 commit adb42e0

File tree

1 file changed

+33
-6
lines changed

1 file changed

+33
-6
lines changed

src/main/java/com/ning/http/client/providers/grizzly/FeedableBodyGenerator.java

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import org.glassfish.grizzly.http.HttpContent;
3030
import org.glassfish.grizzly.http.HttpRequestPacket;
3131
import org.glassfish.grizzly.impl.FutureImpl;
32+
import org.glassfish.grizzly.nio.NIOConnection;
33+
import org.glassfish.grizzly.nio.SelectorRunner;
3234
import org.glassfish.grizzly.ssl.SSLBaseFilter;
3335
import org.glassfish.grizzly.ssl.SSLFilter;
3436
import org.glassfish.grizzly.utils.Futures;
@@ -169,20 +171,46 @@ synchronized void initializeAsynchronousTransfer(final FilterChainContext contex
169171
}
170172
this.context = context;
171173
asyncTransferInitiated = true;
174+
final Runnable r = new Runnable() {
175+
@Override
176+
public void run() {
177+
try {
178+
if (requestPacket.isSecure() &&
179+
(getSSLEngine(context.getConnection()) == null)) {
180+
flushOnSSLHandshakeComplete();
181+
} else {
182+
feeder.flush();
183+
}
184+
} catch (IOException ioe) {
185+
GrizzlyAsyncHttpProvider.HttpTransactionContext ctx =
186+
GrizzlyAsyncHttpProvider.getHttpTransactionContext(
187+
c);
188+
ctx.abort(ioe);
189+
}
190+
}
191+
};
172192

173-
if (requestPacket.isSecure() &&
174-
(getSSLEngine(context.getConnection()) == null)) {
175-
flushOnSSLHandshakeComplete();
193+
// If the current thread is a selector thread, we need to execute
194+
// the remainder of the task on the worker thread to prevent
195+
// it from being blocked.
196+
if (isCurrentThreadSelectorRunner()) {
197+
c.getTransport().getWorkerThreadPool().execute(r);
176198
} else {
177-
feeder.flush();
199+
r.run();
178200
}
179-
180201
}
181202

182203

183204
// --------------------------------------------------------- Private Methods
184205

185206

207+
private boolean isCurrentThreadSelectorRunner() {
208+
final NIOConnection c = (NIOConnection) context.getConnection();
209+
final SelectorRunner runner = c.getSelectorRunner();
210+
return (Thread.currentThread() == runner.getRunnerThread());
211+
}
212+
213+
186214
private void flushOnSSLHandshakeComplete() throws IOException {
187215
final FilterChain filterChain = context.getFilterChain();
188216
final int idx = filterChain.indexOfType(SSLFilter.class);
@@ -331,7 +359,6 @@ private static void blockUntilQueueFree(final Connection c) {
331359
if (!c.canWrite()) {
332360
final FutureImpl<Boolean> future =
333361
Futures.createSafeFuture();
334-
335362
// Connection may be obtained by calling FilterChainContext.getConnection().
336363
c.notifyCanWrite(new WriteHandler() {
337364

0 commit comments

Comments
 (0)