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

use daemon threads to allow shut down of application #748

Merged
merged 2 commits into from
Sep 23, 2023

Conversation

petersv5
Copy link
Contributor

This is an alternative to #744.

To exit normally all non-daemon threads of the java process are supposed to have stopped. TcpClientSession creates an static class member EventLoopGroup which in turn instantiates worker threads. These are changed to daemon threads to not get in the way of the shutdown. This is similar to the default in Netty 5.

To ensure work is finishd the Runtime shutdown event is hooked to initiate a time-limited graceful shutdown of the event loops. Normally an application should shut down communication before the process shutdown is inititated.

@petersv5
Copy link
Contributor Author

The TcpCLientSession change has been successfully tested with Geyser (not pushed to Geyser yet pending further discussion here). TcpSession is not tested yet.

petersv5 pushed a commit to petersv5/Geyser that referenced this pull request Aug 13, 2023
To exit normally all non-daemon threads of the java process
are supposed to have stopped. There are several cases of
EventLoopGroup-created thread pools that are not shut down
as a part of the server shutdown.

These threads are spawned on the first Bedrock player login. The
identified cases are:
- The listener threads in GeyserServerInitializer
- The player threads in GeyserServerInitializer
- The EXECUTOR_SERVICE in the SkinProvider

This patch depends on the PR
GeyserMC/MCProtocolLib#748
submitted to MCProtocolLib to allow the TcpCLientSession to
shut down on process exit.

This is a very quickly thrown together proof of concept to verify that
the execution thread pools left running were what blocked a clean exit
with Geyser active.

Nullify EventLoopGroup variables after shutdown to allow them to be
restarted.
@petersv5
Copy link
Contributor Author

This patch should resolve #699, needs testing.

@Luluno01
Copy link

I'm not a heavy user of Java but just out of curious, how does providing a DefaultThreadFactory allow shutdownGracefully to shutdown all the threads while it didn't really work before? Does DefaultThreadFactory create daemon threads by default?

@petersv5
Copy link
Contributor Author

The second parameter to DefaultThreadFactory indicates daemon threads.

shutdownGracefully() has always worked. What did not work before was hooking the shutdown event to do the shutdownGracefully() as that event was never fired due to the lingering threads. Daemon threads do not veto shutdown, hence the Runtime object decides to shut down the process, calling the hooks etc.

@Luluno01
Copy link

Okay, thanks for the explanation! But would marking all worker threads as daemon threads hurt the performance when they do need to work, as daemon thread has lower priority to the best of my knowledge?

@petersv5
Copy link
Contributor Author

I don't think there is any change in priority when a thread is marked as daemon. I have not checked if DefaultThreadFactory does that, but it likely don't. It is a pretty of netty, so knows it needs a reasonable priority.

@Luluno01
Copy link

Oh yes I've verified their priorities by printing them out. They have the same priority as the main thread, which is 5 in my case. Sorry for the confusion.

@petersv5
Copy link
Contributor Author

Do we want to move forward with this direction and close #744?
Anything else that needs doing?

@Luluno01
Copy link

Apparently they are too busy to review your code...

@Konicai
Copy link
Member

Konicai commented Aug 14, 2023

I wouldn't take it personally – the team does tend to be generally busy and it was the weekend. We really do appreciate what is being done here though <3

Some internal discussion was initiated but it should be wrapped up soon

@petersv5
Copy link
Contributor Author

I have no urgency, so no problem there for me.
I was just curious which way we want to take this and if there was something else do be done.

@Luluno01
Copy link

Luluno01 commented Aug 14, 2023

Not meant to blame anyone but was suggesting that it's probably going to be a while before the developers have time to handle this. Really appreciate such an open-source project where issues are actively discussed and solved.👍

petersv5 pushed a commit to petersv5/Geyser that referenced this pull request Aug 21, 2023
To exit normally all non-daemon threads of the java process
are supposed to have stopped. There are several cases of
EventLoopGroup-created thread pools that are not shut down
as a part of the server shutdown.

These threads are spawned on the first Bedrock player login. The
identified cases are:
- The listener threads in GeyserServerInitializer
- The player threads in GeyserServerInitializer
- The EXECUTOR_SERVICE in the SkinProvider

This patch depends on the PR
GeyserMC/MCProtocolLib#748
submitted to MCProtocolLib to allow the TcpCLientSession to
shut down on process exit.

This is a very quickly thrown together proof of concept to verify that
the execution thread pools left running were what blocked a clean exit
with Geyser active.

Nullify EventLoopGroup variables after shutdown to allow them to be
restarted.
petersv5 pushed a commit to petersv5/Geyser that referenced this pull request Sep 3, 2023
To exit normally all non-daemon threads of the java process
are supposed to have stopped. There are several cases of
EventLoopGroup-created thread pools that are not shut down
as a part of the server shutdown.

These threads are spawned on the first Bedrock player login. The
identified cases are:
- The listener threads in GeyserServerInitializer
- The player threads in GeyserServerInitializer
- The EXECUTOR_SERVICE in the SkinProvider

This patch depends on the PR
GeyserMC/MCProtocolLib#748
submitted to MCProtocolLib to allow the TcpCLientSession to
shut down on process exit.

This is a very quickly thrown together proof of concept to verify that
the execution thread pools left running were what blocked a clean exit
with Geyser active.

Nullify EventLoopGroup variables after shutdown to allow them to be
restarted.
@petersv5
Copy link
Contributor Author

petersv5 commented Sep 6, 2023

Anything we can assist with here to help get it in shape before 1.20.2?

petersv5 pushed a commit to petersv5/Geyser that referenced this pull request Sep 21, 2023
To exit normally all non-daemon threads of the java process
are supposed to have stopped. There are several cases of
EventLoopGroup-created thread pools that are not shut down
as a part of the server shutdown.

These threads are spawned on the first Bedrock player login. The
identified cases are:
- The listener threads in GeyserServerInitializer
- The player threads in GeyserServerInitializer
- The EXECUTOR_SERVICE in the SkinProvider

This patch depends on the PR
GeyserMC/MCProtocolLib#748
submitted to MCProtocolLib to allow the TcpCLientSession to
shut down on process exit.

This is a very quickly thrown together proof of concept to verify that
the execution thread pools left running were what blocked a clean exit
with Geyser active.

Nullify EventLoopGroup variables after shutdown to allow them to be
restarted.
@Konicai
Copy link
Member

Konicai commented Sep 22, 2023

The second parameter to DefaultThreadFactory indicates daemon threads.

shutdownGracefully() has always worked. What did not work before was hooking the shutdown event to do the shutdownGracefully() as that event was never fired due to the lingering threads. Daemon threads do not veto shutdown, hence the Runtime object decides to shut down the process, calling the hooks etc.

Can we add a concise comment about the 2nd parameter and about the shutdown process to one of the classes? and then in the other class its probably just fine to refer to the other class for documentation about this.

@petersv5
Copy link
Contributor Author

The second parameter to DefaultThreadFactory indicates daemon threads.

shutdownGracefully() has always worked. What did not work before was hooking the shutdown event to do the shutdownGracefully() as that event was never fired due to the lingering threads. Daemon threads do not veto shutdown, hence the Runtime object decides to shut down the process, calling the hooks etc.

Can we add a concise comment about the 2nd parameter and about the shutdown process to one of the classes? and then in the other class its probably just fine to refer to the other class for documentation about this.

Want me to add it, or will you guys take over updating the PR?
Either way is fine by me.

petersv5 pushed a commit to petersv5/Geyser that referenced this pull request Sep 22, 2023
To exit normally all non-daemon threads of the java process
are supposed to have stopped. There are several cases of
EventLoopGroup-created thread pools that are not shut down
as a part of the server shutdown.

These threads are spawned on the first Bedrock player login. The
identified cases are:
- The listener threads in GeyserServerInitializer
- The player threads in GeyserServerInitializer
- The EXECUTOR_SERVICE in the SkinProvider

This patch depends on the PR
GeyserMC/MCProtocolLib#748
submitted to MCProtocolLib to allow the TcpCLientSession to
shut down on process exit.

This is a very quickly thrown together proof of concept to verify that
the execution thread pools left running were what blocked a clean exit
with Geyser active.

Nullify EventLoopGroup variables after shutdown to allow them to be
restarted.
To exit normally all non-daemon threads of the java process are supposed
to have stopped. TcpClientSession creates an static class member
EventLoopGroup which in turn instantiates worker threads. These are
changed to daemon threads to not get in the way of the shutdown. This
is similar to the default in Netty 5.

To ensure work is finishd the Runtime shutdown event is hooked to
initiate a time-limited graceful shutdown of the event loops. Normally
an application should shut down communication before the process
shutdown is inititated.
@petersv5 petersv5 force-pushed the daemon_thread_executor branch from 35a12e3 to 46595e2 Compare September 22, 2023 16:53
@petersv5
Copy link
Contributor Author

Pushed my proposal for comments.

@Konicai Konicai merged commit d85e90f into GeyserMC:master Sep 23, 2023
1 check failed
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