Skip to content

Gracefully shutdown example servers #6512

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

Merged
merged 9 commits into from
Dec 14, 2019

Conversation

dounan
Copy link
Contributor

@dounan dounan commented Dec 11, 2019

The example servers do not properly wait until preexisting calls complete before shutting down (#6511).

This PR

  • Adds a call to awaitTermination to wait for preexisting calls to complete (with a 30s timeout)
  • Updates the API documentation for Server.shutdown to clarify that the call does not wait for preexisting calls to complete before returning.

@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Dec 11, 2019

CLA Check
The committers are authorized under a signed CLA.

Copy link
Member

@ejona86 ejona86 left a comment

Choose a reason for hiding this comment

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

Hmmm... something else is going on. The blockUntilShutdown() in the main() should be enough...

@@ -104,8 +104,8 @@ public int getPort() {

/**
* Initiates an orderly shutdown in which preexisting calls continue but new calls are rejected.
Copy link
Member

Choose a reason for hiding this comment

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

I think "initiates" is the key word here.

I think this would probably go better as a second paragraph that is merely informative. Something like:

Note that this method does not wait for the server to stop, so existing calls may continue after returning. To stop existing calls use {@link #shutdownNow()} and to wait for the server to fully stop use {@link #awaitTermination()}.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Combined your and @sanjaypujare's suggestions: af9a157

* After this call returns, this server has released the listening socket(s) and may be reused by
* another server.
* This call will not wait for preexisting calls finish before returning. After this call returns,
* this server has released the listening socket(s) and may be reused by another server.
Copy link
Contributor

Choose a reason for hiding this comment

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

I suggest the following:

Initiates an orderly shutdown to allow preexisting calls to continue but new calls are
rejected. {@link #awaitTermination()} or {@link #awaitTermination(long, TimeUnit)} needs
to be called to wait for existing calls to finish. After this call returns, this server
has released the listening socket(s) and may be reused by another server.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Combined your and @ejona86's suggestions: af9a157

@dounan
Copy link
Contributor Author

dounan commented Dec 11, 2019

Thanks for taking a look @ejona86!

Hmmm... something else is going on. The blockUntilShutdown() in the main() should be enough...

From my understanding, the blockUntilShutdown() is useful to keep the Java application running so that the gRPC can serve requests, which is a bit different than handling the JVM's shutdown process.

When the JVM is instructed to shutdown (such as via a SIGINT), it will call all registered shutdown handlers that are registered via addShutdownHook:

Runtime.getRuntime().addShutdownHook(new Thread() {
    @Override
    public void run() {
        ...
    }
});

Once all those run methods return, the JVM will shutdown.

For this reason, it is important for the shutdown hook's run() method to not return until you are ok with the JVM shutting down, hence the additional call to server.awaitTermination()

@sanjaypujare
Copy link
Contributor

Hmmm... something else is going on. The blockUntilShutdown() in the main() should be enough...

When you press control-C, it invokes the shutdown-hook. So blockUntilShutdown() in the main() is skipped right? In the original issue @dounan mentioned pressing control-C.

@ejona86
Copy link
Member

ejona86 commented Dec 11, 2019

Once all those run methods return, the JVM will shutdown.

That's not true. On ctrl-c, the JVM simply calls start() on the threads registered, and nothing really more. What causes JVM shutdown is when there are no non-daemon threads. The main thread is non-daemon, so it should keep the JVM alive.

@ejona86
Copy link
Member

ejona86 commented Dec 11, 2019

I'm going to move the conversation back to issue #6511.

Copy link
Member

@ejona86 ejona86 left a comment

Choose a reason for hiding this comment

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

The new documentation looks good to me. I want to hold off on adding the awaitTerminations until we gain a bit better understanding what is going on.

* After this call returns, this server has released the listening socket(s) and may be reused by
* another server.
*
* Note that this method will not wait for preexisting calls finish before returning.
Copy link
Contributor

Choose a reason for hiding this comment

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

preexisting calls finish => preexisting calls to finish

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Doh! Good catch

@dounan dounan force-pushed the gracefully-shutdown-example-servers branch from af9a157 to 3328bfc Compare December 11, 2019 19:23
Copy link
Member

@ejona86 ejona86 left a comment

Choose a reason for hiding this comment

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

Okay. So I was wrong, we do need the hook to wait until the server is done.

@dounan dounan force-pushed the gracefully-shutdown-example-servers branch from 3328bfc to 7bd69d3 Compare December 11, 2019 19:57
Copy link
Member

@ejona86 ejona86 left a comment

Choose a reason for hiding this comment

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

One small thing, otherwise looks good. Thank you!

@ejona86 ejona86 added the kokoro:run Add this label to a PR to tell Kokoro the code is safe and tests can be run label Dec 11, 2019
@grpc-kokoro grpc-kokoro removed the kokoro:run Add this label to a PR to tell Kokoro the code is safe and tests can be run label Dec 11, 2019
@ejona86 ejona86 requested a review from sanjaypujare December 11, 2019 23:05
try {
CompressingHelloWorldServerAllMethods.this.stop();
} catch (InterruptedException e) {
e.printStackTrace();
Copy link
Contributor

Choose a reason for hiding this comment

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

Couple of comments:

  • do you want to print to stderr in keeping with lines 65 and 71?
    e.printStackTrace(System.err)

  • do you want to mention/comment saying this is because the logger is closed as part of shutdown?

and of course make this change everywhere.

Copy link
Contributor Author

@dounan dounan Dec 12, 2019

Choose a reason for hiding this comment

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

do you want to print to stderr in keeping with lines 65 and 71?
e.printStackTrace(System.err)

Done in d997e5b

I also went ahead and fixed the call to logger in ManualFlowControlServer: 1df260a

do you want to mention/comment saying this is because the logger is closed as part of shutdown?

The call to System.err.println above already has this comment 😄

Copy link
Contributor

@sanjaypujare sanjaypujare left a comment

Choose a reason for hiding this comment

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

I have suggested a couple of changes.

Copy link
Contributor

@sanjaypujare sanjaypujare left a comment

Choose a reason for hiding this comment

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

LGTM

@sanjaypujare sanjaypujare added the kokoro:force-run Add this label to a PR to tell Kokoro to re-run all tests. Not generally necessary label Dec 13, 2019
@grpc-kokoro grpc-kokoro removed the kokoro:force-run Add this label to a PR to tell Kokoro to re-run all tests. Not generally necessary label Dec 13, 2019
@sanjaypujare sanjaypujare merged commit 9e02cf0 into grpc:master Dec 14, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Mar 17, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants