Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't handle http2 errors in StaticHandler AsyncFile #2580

Closed
cavallium opened this issue Mar 13, 2024 · 1 comment
Closed

Can't handle http2 errors in StaticHandler AsyncFile #2580

cavallium opened this issue Mar 13, 2024 · 1 comment
Assignees
Labels
Milestone

Comments

@cavallium
Copy link

Version

4.5.4

Context

I have a StaticHandler with async fs enabled.
When I handle the requests with a HTTP2 server, if a client closes the connection after fetching the first x bytes, the internal AsyncFile does not have any failure handler, so it prints an unhandled exception in the log output:

var staticRoute = router.route(staticRoot + "/*")
    .handler(StaticHandler.create(staticFileRoot)
        .setCachingEnabled(cacheEnabled)
        .setEnableRangeSupport(true)
        .setEnableFSTuning(true)
        .setSendVaryHeader(true)
        .setMaxAgeSeconds(maxStaticFileCacheSeconds)
        .setFilesReadOnly(true))
    .failureHandler(errorHandler);
Exception

2024-03-13 17:54:27.722 ERROR 141868 AsyncFile            : Unhandled exception
java.nio.channels.ClosedChannelException
	at java.base/sun.nio.ch.SimpleAsynchronousFileChannelImpl.implRead(SimpleAsynchronousFileChannelImpl.java:307)
	at java.base/sun.nio.ch.AsynchronousFileChannelImpl.read(AsynchronousFileChannelImpl.java:229)
	at io.vertx.core@4.5.4/io.vertx.core.file.impl.AsyncFileImpl.doRead(AsyncFileImpl.java:510)
	at io.vertx.core@4.5.4/io.vertx.core.file.impl.AsyncFileImpl.doRead(AsyncFileImpl.java:418)
	at io.vertx.core@4.5.4/io.vertx.core.file.impl.AsyncFileImpl.doRead(AsyncFileImpl.java:397)
	at io.vertx.core@4.5.4/io.vertx.core.file.impl.AsyncFileImpl.lambda$new$1(AsyncFileImpl.java:120)
	at io.vertx.core@4.5.4/io.vertx.core.streams.impl.InboundBuffer.handleEvent(InboundBuffer.java:255)
	at io.vertx.core@4.5.4/io.vertx.core.streams.impl.InboundBuffer.drain(InboundBuffer.java:245)
	at io.vertx.core@4.5.4/io.vertx.core.streams.impl.InboundBuffer.lambda$fetch$0(InboundBuffer.java:295)
	at io.vertx.core@4.5.4/io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:276)
	at io.vertx.core@4.5.4/io.vertx.core.impl.ContextInternal.dispatch(ContextInternal.java:258)
	at io.vertx.core@4.5.4/io.vertx.core.impl.ContextInternal.lambda$runOnContext$0(ContextInternal.java:56)
	at io.netty.common@4.1.107.Final/io.netty.util.concurrent.AbstractEventExecutor.runTask$$$capture(AbstractEventExecutor.java:173)
	at io.netty.common@4.1.107.Final/io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java)
	at io.netty.common@4.1.107.Final/io.netty.util.concurrent.AbstractEventExecutor.safeExecute$$$capture(AbstractEventExecutor.java:166)
	at io.netty.common@4.1.107.Final/io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java)
	at io.netty.common@4.1.107.Final/io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470)
	at io.netty.transport@4.1.107.Final/io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:566)
	at io.netty.common@4.1.107.Final/io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
	at io.netty.common@4.1.107.Final/io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.common@4.1.107.Final/io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:1583)

Do you have a reproducer?

I don't have a reproducer, but if you look at the stacktrace, the problem is simple: the StaticHandler does not set a failure handle in the AsyncFile, and it does not even expose a way to set it, so it's impossible to handle the exception in any way.

Steps to reproduce

  1. Create a http2 webserver
  2. Add a StaticHandler in the root path
  3. Enable async fs in the StaticHandler
  4. Start a file request of a big file, like a video, but cancel it after fetching some initial bytes (like a browser does to fetch the first video frames)
  5. That unhandled error will be printed in the console

Extra

  • Anything that can be relevant such as OS version, JVM version
@cavallium cavallium added the bug label Mar 13, 2024
@tsegismont tsegismont self-assigned this Mar 18, 2024
@tsegismont tsegismont added this to the 4.5.6 milestone Mar 18, 2024
@vietj vietj modified the milestones: 4.5.6, 4.5.7, 4.5.8 Mar 21, 2024
@vietj vietj assigned vietj and unassigned tsegismont May 23, 2024
@vietj
Copy link
Contributor

vietj commented May 23, 2024

This is a side effect of piping an async file to HTTP/2 that does not stop when the corresponding pipe fails, see eclipse-vertx/vert.x#5211

@vietj vietj closed this as completed May 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

3 participants