Skip to content

Commit 9f6ab74

Browse files
ulfjacklaurentlb
authored andcommitted
Complete channel initialization in the event loop
If addLast is called outside an event loop, then the handler is added in the 'pending' state. Sending an event to the pipeline does not send it to the last handler, but to the last _non-pending_ handler. We therefore have to make sure to involve the event loop _before_ marking the channel as ready to be used. Thanks to @Reflexe who pointed me in the right direction. Fixes #7464. Closes #7509. GERRIT_CHANGE_ID= PiperOrigin-RevId: 235184010
1 parent d2fd660 commit 9f6ab74

File tree

1 file changed

+20
-2
lines changed

1 file changed

+20
-2
lines changed

src/main/java/com/google/devtools/build/lib/remote/blobstore/http/HttpBlobStore.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,16 @@ private Channel acquireUploadChannel() throws InterruptedException {
271271
p.addLast(new HttpUploadHandler(creds));
272272
}
273273

274-
channelReady.setSuccess(ch);
274+
if (!ch.eventLoop().inEventLoop()) {
275+
// If addLast is called outside an event loop, then it doesn't complete until the
276+
// event loop is run again. In that case, a message sent to the last handler gets
277+
// delivered to the last non-pending handler, which will most likely end up
278+
// throwing UnsupportedMessageTypeException. Therefore, we only complete the
279+
// promise in the event loop.
280+
ch.eventLoop().execute(() -> channelReady.setSuccess(ch));
281+
} else {
282+
channelReady.setSuccess(ch);
283+
}
275284
} catch (Throwable t) {
276285
channelReady.setFailure(t);
277286
}
@@ -332,7 +341,16 @@ private Future<Channel> acquireDownloadChannel() {
332341
p.addLast(new HttpDownloadHandler(creds));
333342
}
334343

335-
channelReady.setSuccess(ch);
344+
if (!ch.eventLoop().inEventLoop()) {
345+
// If addLast is called outside an event loop, then it doesn't complete until the
346+
// event loop is run again. In that case, a message sent to the last handler gets
347+
// delivered to the last non-pending handler, which will most likely end up
348+
// throwing UnsupportedMessageTypeException. Therefore, we only complete the
349+
// promise in the event loop.
350+
ch.eventLoop().execute(() -> channelReady.setSuccess(ch));
351+
} else {
352+
channelReady.setSuccess(ch);
353+
}
336354
} catch (Throwable t) {
337355
channelReady.setFailure(t);
338356
}

0 commit comments

Comments
 (0)