vert.x icon indicating copy to clipboard operation
vert.x copied to clipboard

Http2ClientConnection attempts to write to a null stream when write queued

Open zekronium opened this issue 1 year ago • 0 comments

Version

4.5.9 and above (this part of the vertx code has not been changed for a while now so likely is in older versions too)

Context

Using the Http2Client (via WebClient), the createStream fails due to the connection being closed before stream is created, thus init(stream) is never called. In createStream the call to create the child stream Http2Stream stream = this.conn.handler.encoder().connection().local().createStream(id, false); fails with the connection being closed error.

https://github.com/eclipse-vertx/vert.x/blob/00fa55682875b7e380ad6328708581ed25d96a9f/src/main/java/io/vertx/core/http/impl/Http2ClientConnection.java#L588-L602

https://github.com/eclipse-vertx/vert.x/blob/00fa55682875b7e380ad6328708581ed25d96a9f/src/main/java/io/vertx/core/http/impl/Http2ClientConnection.java#L605-L628

where init stream is set to be used by the VertxHttp2Stream

  void init(Http2Stream stream) {
    synchronized (this) {
      this.stream = stream;
      this.writable = this.conn.handler.encoder().flowController().isWritable(stream);
    }
    stream.setProperty(conn.streamKey, this);
  }

At first glance, everything is ok, exception is handled, handler is called, yet while using virtual threads, which always causes writes to queue due to the non even-loop condition !eventLoop.inEventLoop(), the stream appears to try writing to a null stream.

  void writeData(Http2Stream stream, ByteBuf chunk, boolean end, FutureListener<Void> listener) {
    ChannelPromise promise = listener == null ? chctx.voidPromise() : chctx.newPromise().addListener(listener);
    encoder().writeData(chctx, stream.id(), chunk, 0, end, promise); //stream is null here so stream.id() throws NPE
    Http2RemoteFlowController controller = encoder().flowController();
    if (!controller.isWritable(stream) || end) {
      try {
        encoder().flowController().writePendingBytes();
      } catch (Http2Exception e) {
        onError(chctx, true, e);
      }
    }
    checkFlush();
  }
[WARN]|AbstractEventExecutor| > A task raised an exception. Task: io.vertx.core.http.impl.VertxHttp2Stream$$Lambda/0x0000000800546148@771dbe57
java.lang.NullPointerException: Cannot invoke "io.netty.handler.codec.http2.Http2Stream.id()" because "stream" is null
	at io.vertx.core.http.impl.VertxHttp2ConnectionHandler.writeData(VertxHttp2ConnectionHandler.java:251) 
	at io.vertx.core.http.impl.VertxHttp2Stream.doWriteData(VertxHttp2Stream.java:252)
	at io.vertx.core.http.impl.Http2ClientConnection$Stream.doWriteData(Http2ClientConnection.java:297)
	at io.vertx.core.http.impl.VertxHttp2Stream.lambda$writeData$7(VertxHttp2Stream.java:217)
	at io.vertx.core.http.impl.VertxHttp2Stream.lambda$queueForWrite$8(VertxHttp2Stream.java:234) 
	at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:173) ~[netty-common-4.1.111.Final.jar:4.1.111.Final]
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:166) ~[netty-common-4.1.111.Final.jar:4.1.111.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:469) ~[netty-common-4.1.111.Final.jar:4.1.111.Final]
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:566) ~[netty-transport-4.1.111.Final.jar:4.1.111.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:994) ~[netty-common-4.1.111.Final.jar:4.1.111.Final]
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.111.Final.jar:4.1.111.Final]
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.111.Final.jar:4.1.111.Final]
	at java.base/java.lang.Thread.run(Thread.java:1583) [?:?]

Do you have a reproducer?

Simulate connection closure while setting up the connection. Use virtual threads.

Extra

Windows Server, Temurin JDK 21.0.3

zekronium avatar Oct 02 '24 18:10 zekronium