Skip to content

IoUring: Correctly drain all IO events before shutdown the EventLoop …#14877

Merged
normanmaurer merged 1 commit into4.2from
drain_on_prepare
Mar 3, 2025
Merged

IoUring: Correctly drain all IO events before shutdown the EventLoop …#14877
normanmaurer merged 1 commit into4.2from
drain_on_prepare

Conversation

@normanmaurer
Copy link
Copy Markdown
Member

…and so not accepted any more tasks to be scheduled.

Motivation:

We need to ensure we correctly drain all submissions before we allow to shutdown the EventLoop as otherwise we might not be able to cleanly close a Channel when using io_uring.

Missing to do so results in exception during shutdown:

[io.netty.channel.AbstractChannel]: Can't invoke task later as EventLoop rejected it
java.util.concurrent.RejectedExecutionException: event executor terminated
        at io.netty.util.concurrent.SingleThreadEventExecutor.reject(SingleThreadEventExecutor.java:1005) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.util.concurrent.SingleThreadEventExecutor.offerTask(SingleThreadEventExecutor.java:388) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.util.concurrent.SingleThreadEventExecutor.addTask(SingleThreadEventExecutor.java:381) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:907) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.util.concurrent.SingleThreadEventExecutor.execute0(SingleThreadEventExecutor.java:873) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:863) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.AbstractChannel$AbstractUnsafe.invokeLater(AbstractChannel.java:888) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.AbstractChannel$AbstractUnsafe.deregister(AbstractChannel.java:668) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.AbstractChannel$AbstractUnsafe.fireChannelInactiveAndDeregister(AbstractChannel.java:628) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.AbstractChannel$AbstractUnsafe.close(AbstractChannel.java:611) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.uring.AbstractIoUringChannel$AbstractUringUnsafe.closeNow(AbstractIoUringChannel.java:589) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.uring.AbstractIoUringChannel$AbstractUringUnsafe.handleDelayedClosed(AbstractIoUringChannel.java:499) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.uring.AbstractIoUringChannel$AbstractUringUnsafe.handle(AbstractIoUringChannel.java:425) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.uring.IoUringIoHandler$DefaultIoUringIoRegistration.handle(IoUringIoHandler.java:562) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.uring.IoUringIoHandler.handle(IoUringIoHandler.java:267) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.uring.CompletionQueue.process(CompletionQueue.java:95) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.uring.IoUringIoHandler.destroy(IoUringIoHandler.java:366) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.SingleThreadIoEventLoop.cleanup(SingleThreadIoEventLoop.java:245) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:1147) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at java.lang.Thread.run(Thread.java:1575) [?:?]

Modifications:

Correctly drain before return from method.

Result:

No more exception during shutdown. Fixes #14872

…and so not accepted any more tasks to be scheduled.

Motivation:

We need to ensure we correctly drain all submissions before we allow to shutdown the EventLoop as otherwise we might not be able to cleanly close a Channel when using io_uring.

Missing to do so results in exception during shutdown:

```
[io.netty.channel.AbstractChannel]: Can't invoke task later as EventLoop rejected it
java.util.concurrent.RejectedExecutionException: event executor terminated
        at io.netty.util.concurrent.SingleThreadEventExecutor.reject(SingleThreadEventExecutor.java:1005) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.util.concurrent.SingleThreadEventExecutor.offerTask(SingleThreadEventExecutor.java:388) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.util.concurrent.SingleThreadEventExecutor.addTask(SingleThreadEventExecutor.java:381) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:907) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.util.concurrent.SingleThreadEventExecutor.execute0(SingleThreadEventExecutor.java:873) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:863) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.AbstractChannel$AbstractUnsafe.invokeLater(AbstractChannel.java:888) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.AbstractChannel$AbstractUnsafe.deregister(AbstractChannel.java:668) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.AbstractChannel$AbstractUnsafe.fireChannelInactiveAndDeregister(AbstractChannel.java:628) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.AbstractChannel$AbstractUnsafe.close(AbstractChannel.java:611) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.uring.AbstractIoUringChannel$AbstractUringUnsafe.closeNow(AbstractIoUringChannel.java:589) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.uring.AbstractIoUringChannel$AbstractUringUnsafe.handleDelayedClosed(AbstractIoUringChannel.java:499) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.uring.AbstractIoUringChannel$AbstractUringUnsafe.handle(AbstractIoUringChannel.java:425) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.uring.IoUringIoHandler$DefaultIoUringIoRegistration.handle(IoUringIoHandler.java:562) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.uring.IoUringIoHandler.handle(IoUringIoHandler.java:267) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.uring.CompletionQueue.process(CompletionQueue.java:95) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.uring.IoUringIoHandler.destroy(IoUringIoHandler.java:366) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.channel.SingleThreadIoEventLoop.cleanup(SingleThreadIoEventLoop.java:245) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:1147) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[x.jar:git:Waterfall-Bootstrap:1.21-R0.1-SNAPSHOT:289f726:unknown]
        at java.lang.Thread.run(Thread.java:1575) [?:?]
```

Modifications:

Correctly drain before return from method.

Result:

No more exception during shutdown. Fixes #14872
@normanmaurer
Copy link
Copy Markdown
Member Author

/cc @andreasdc

@andreasdc
Copy link
Copy Markdown

/cc @andreasdc

So fast fix, keep up the good work! 💪🚀

Copy link
Copy Markdown
Contributor

@franz1981 franz1981 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM quick one!

@normanmaurer normanmaurer merged commit b5bcc1b into 4.2 Mar 3, 2025
16 of 17 checks passed
@normanmaurer normanmaurer deleted the drain_on_prepare branch March 3, 2025 06:44
@andreasdc andreasdc mentioned this pull request Aug 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants