RFR: 8376479: Http3 test server thread deadlock in ThrowingPublishersInRequest [v3]
Volkan Yazici
vyazici at openjdk.org
Thu Jan 29 18:16:47 UTC 2026
On Thu, 29 Jan 2026 14:53:18 GMT, Daniel Jeliński <djelinski at openjdk.org> wrote:
>> This fixes a deadlock between the thread that reads from the RequestBodyInputStream and the thread that tries to close it in response to a stream reset. See the linked JBS ticket for details.
>>
>> Tier1 and tier2 tests continue to pass. I verified that with this change there are no busy threads at the end of the test.
>
> Daniel Jeliński has updated the pull request incrementally with two additional commits since the last revision:
>
> - Send stop_sending if the InputStream is closed
> - Close the stream atomically
test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http3/Http3ServerStreamImpl.java line 336:
> 334: Thread.currentThread().interrupt();
> 335: io.initCause(e);
> 336: throw io;
Can we simplify this loop as follows?
Suggestion:
while (true) {
Object reason = closeReason.get();
if (reason == Boolean.TRUE) {
throw new IOException("Stream is closed");
} else if (reason instanceof IOException ioe) {
throw new IOException(ioe);
}
if (current != null && (current.hasRemaining() || current == QuicStreamReader.EOF)) {
return current;
}
try {
if (debug.on())
debug.log("Taking buffer from queue");
// Blocking call
current = requestBodyQueue.take();
} catch (InterruptedException e) {
var io = new InterruptedIOException();
Thread.currentThread().interrupt();
io.initCause(e);
throw io;
test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http3/Http3ServerStreamImpl.java line 368:
> 366: @Override
> 367: public void close() throws IOException {
> 368: if (closeReason.getAndSet(Boolean.TRUE) == Boolean.TRUE) return;
Shouldn't this be `!compareAndSet(null, TRUE)`? Otherwise we allow changing the state from `FAILED` to `CLOSED`, which, AFAICT, is not intended.
test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http3/Http3ServerStreamImpl.java line 371:
> 369: if (debug.on())
> 370: debug.log("Closing request body input stream");
> 371: requestBodyQueue.add(QuicStreamReader.EOF);
Do we need `requestBodyQueue.add(QuicStreamReader.EOF)` here and in `resetStream`, given `read()` will propagate the non-null `closeReason` thrown by `current()` anyway, and `current()` is the only reader of `requestBodyQueue`?
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/29448#discussion_r2742919788
PR Review Comment: https://git.openjdk.org/jdk/pull/29448#discussion_r2742812024
PR Review Comment: https://git.openjdk.org/jdk/pull/29448#discussion_r2742823607
More information about the net-dev
mailing list