question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

`SingleThreadEventExecutor.shutdownGracefully` starts thread to shut it down?

See original GitHub issue

Expected behavior

If shutdownGracefully is called on a SingleThreadEventExecutor that has not created a thread yet, the executor should shutdown without creating a thread.

Actual behavior

If shutdownGracefully is called on SingleThreadEventExecutor, ensureThreadStarted will be called in line #660, which will start the thread, to then? I don’t know? Shut it down? I do not get behind the logic to return the terminationFuture in that case.

Steps to reproduce

Create any kind of EventLoopGroup, without putting work on it, shut it down gracefully and threads will be created.

Minimal yet complete reproducer code (or URL to code)

public static void main(String[] args) {
    EventLoopGroup group = new NioEventLoopGroup(1, runnable -> {
        return new Thread(runnable) {
            {
                new IllegalStateException("I was created, because Netty wants to shut me down :(")
                        .printStackTrace();
            }
        };
    });
    group.shutdownGracefully();
}

Will print:

java.lang.IllegalStateException: I was created, because Netty wants to shut me down :(
        ...
        at io.netty.util.concurrent.ThreadPerTaskExecutor.execute(ThreadPerTaskExecutor.java:32)
        at io.netty.util.internal.ThreadExecutorMap$1.execute(ThreadExecutorMap.java:57)
        at io.netty.util.concurrent.SingleThreadEventExecutor.doStartThread(SingleThreadEventExecutor.java:978)
        at io.netty.util.concurrent.SingleThreadEventExecutor.ensureThreadStarted(SingleThreadEventExecutor.java:961)
        at io.netty.util.concurrent.SingleThreadEventExecutor.shutdownGracefully(SingleThreadEventExecutor.java:663)
        at io.netty.util.concurrent.MultithreadEventExecutorGroup.shutdownGracefully(MultithreadEventExecutorGroup.java:163)
        at io.netty.util.concurrent.AbstractEventExecutorGroup.shutdownGracefully(AbstractEventExecutorGroup.java:70)
        ...

Netty version

4.1

JVM version (e.g. java -version)

openjdk 11.0.12 2021-07-20 LTS OpenJDK Runtime Environment SapMachine (build 11.0.12+7-LTS-sapmachine) OpenJDK 64-Bit Server VM SapMachine (build 11.0.12+7-LTS-sapmachine, mixed mode)

OS version (e.g. uname -a)

Windows 10

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:2
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
kristiancommented, Sep 17, 2021

Hey @NiteshKant, I think I have some good news to share, all thanks to your reply, as it got me thinking, so thanks for that!

I believe I found out the root cause of my assumption, why Vert.x is not “completing” as I thought it would: Calling vertx.close() will shut down all the event loop threads, created by Vert.x, gracefully, as I mentioned, by calling the shutdownGracefully method on all EventLoopGroups created by Vert.x. However, what I didn’t think of, is that Vert.x has to dispatch the “close” event somehow to it’s close future, returned by the close method. And (this was my wrong assumption) Vert.x is indeed using the last created event loop thread, to dispatch this very final event. Thus the close future will actually block the final event-loop thread exiting, until it is done executing, being the result of my initial assumption, that it is not properly waiting for it to be closed!

Phew… that was a tricky one to warp my head around! 😉 Thanks a lot for the explanation and help, as you say I don’t think this issue needs further mitigation and it can stay as is. So if you agree, I think we could close it? Good to understand the concept however, so maybe this issue will be useful also to others, which run into this edge case! 👍 Thanks again!

1reaction
kristiancommented, Sep 17, 2021

Hey @NiteshKant, thanks for the elaborate explanation of actually why the threads are created in the first place and I fully support your viewpoint of favouring a more robust / less complex implementation over covering an edge case that should next to never cause major side effects in the first place. As you say: in most (especially productive) applications, all executors should be well in use, before a shutdown is initiated. Our example within unit tests is a extreme case, because we start and tear down Vert.x instances for many of our tests in quick succession.

Do you have any idea / could the current implementation cause the shutdownGracefully future to report a successful shutdown, before the threads are actually gone in the mentioned edge case? Because this is what we somehow observe: Vert.x signaling a shutdown and the threads being created after that. I am willing to do a more in depth analysis on this, as it could be also a flaw in the Vert.x shutdown logic. However afaik, they just end the ThreadPools by calling the graceful shutdown and wait for completion.

I can fully live with what you mentioned, because the edge case doesn‘t really hurt, however if you agree that an early signaled shutdown could be considered an issue (because it is hard to find a workaround for such cases), I would offer take another look into it. What do you think, do you have any hint if and why this could actually happen? Thanks for your effort thus far!

Read more comments on GitHub >

github_iconTop Results From Across the Web

SingleThreadEventExecutor (Netty API Reference (4.0.56.Final))
Returns true if and only if this executor was started to be shut down ... shutdownGracefully(long quietPeriod, long timeout, java.util.concurrent.
Read more >
Discard Server, threads not cleaning up - Google Groups
The I/O threads start lazily, but they keep running until you tell them to shut down via EventLoopGroup.shutdownGracefully().
Read more >
Graceful shutdown of threads and executor - java
The JVM can shut down in either an orderly or abrupt manner. An orderly shutdown is initiated when the last "normal" (nondaemon) thread...
Read more >
GlobalEventExecutor (Netty API Reference (4.1.11.Final))
It starts the thread automatically and stops it when there is no task ... by this EventExecutorGroup are being shut down gracefully or...
Read more >
SingleThreadEventExecutor (Netty 4.1.72.Final API文档
shutdownGracefully (long quietPeriod, long timeout, java.util.concurrent. ... Signals this executor that the caller wants the executor to be shut down.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found