-
Notifications
You must be signed in to change notification settings - Fork 108
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
2862: GracefulShutdown utility #86
Conversation
First of all, the work in here looks really nice!
I think this is probably the best one. You can look at how hyper 0.14.x did it for the internal future logic. Some other thoughts:
|
Great to hear @seanmonstar will look to finish this PR for a first non-draft review this week then, based on this feedback. |
@seanmonstar the clone can only be removed if you only ever want one shutdown? Unless you start stacking shutdowns? |
in replacement of futures in generic
Still to do as well are tests and an example. I'll do this only once you both agree (@seanmonstar and @davidpdrsn) on the current design / implementation. Would rather focus on that and my open questions prior to starting to add testing and examples. |
@seanmonstar and @davidpdrsn I know have a working example: https://github.com/hyperium/hyper-util/blob/8f24314cf040faba15190ff5b75652d3e4c70e52/examples/server_graceful.rs You can play with it yourself. Figured that doing the example already would help me iron out some details myself.
Example works and AFAIK the design is now final and ready for your review. Once you both approve of the design and we worked out some comments you might have, i can finish this off by adding also some unit tests. |
this is now handled automatically based on shutdown call
@seanmonstar and @davidpdrsn , this PR is now ready for "final" review, I am finished. Updates since last time:
There's also an example that you can play with:
Looking forward to the review. As it's my first PR to this organisation I do expect there might be some more back and forward needed. You tell me, as I do think it's ready but 🤷 who knows. |
@seanmonstar is there work to be done here or something I can do to help make this progress. Also if there's something else you have in mind I can look at next, I could take a look at it. The hyper issue seemed interesting but I think I would like to also start contributing a bit to the h2/h3 crates as a way to motivate myself to get more familiar with these. Anything you have in mind? |
Sorry I haven't had the time to review again. I was just out for a week escaping the winter. @programatik29 @dswij @tottoto any of you want to take a look? (Relevant issue and discussion: hyperium/hyper#2862) |
state: Arc<GracefulState>, | ||
// state that the watched futures to know when shutdown signal is received | ||
future_state: Arc<GracefulState>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC, the future_state here is to keep track of all the futures. What does the state
do for GracefulShutdown here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC = If I understand Correctly, didn't know that was a thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naming is hard though. I am essentially using the same concept in two directions.
- the "state" is to keep track of all watchers active. When the
GracefulShutdown
turns into aGracefulWaiter
uponself::shutdown()
it uses it to check when the counter is 0 and thus when shutdown is finished. While it is still aGracefulShutdown
it clones this state and patches it to theGracefulWatchers
(the ones watching the "graceful" connections) to help to do its bookkeeping using this counter - the "future_state" is only ever once incremented (it is the counter of the
GracefulShutdown
itself, of which there is only ever one. And it is used by the "graceful" connections to know if a cancel is triggered. This is essentially "reusing" theGracefulWaiter
logic that was already created for the other direction.
So no probably due to the fault of my part (not sure if bad documentation, naming or code) it seemed that you didn not understand it correctly. As it is the state
which is there to keep track of all the futures (futures as in graceful connections).
pub fn watcher(&self) -> GracefulWatcher { | ||
self.state.subscribe(); | ||
GracefulWatcher { | ||
state: self.state.clone(), | ||
future_state: self.future_state.clone(), | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can spawn multiple GracefulWatcher
from a single GracefulShutdown
, so is it accurate to say that the states in GracefulShutdown is for every watcher and futures?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. That is accurate, all these GracefulWatchers lead to the same GracefulShutdown. Once you shutdown however you consume the GracefulShutdown
and no new graceful watchers can be created.
|
||
struct GracefulWaiterState { | ||
state: Arc<GracefulState>, | ||
key: Option<usize>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does the key
here do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that a question or you want me to comment it? It is the insertion key in the waker list, important for it to be removed again.
.load(std::sync::atomic::Ordering::SeqCst) | ||
== 0 | ||
{ | ||
// check again in case of race condition |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the scenario for race condition here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We first check the counter. That one is zero only if shutdown is already triggered. We then wait for a lock. However it is possible that that we had to wait for the lock while something else was holding the lock to awake the ones waiting for shutdown.
If we do not check again once we have the lock it is possible that the counter in meanwhile is zero. If so we either way need to trigger shutdown here or else we might not be woken up.
This was discovered while developing the origin code on which this PR was inspired (https://github.com/plabayo/tokio-graceful, a crate of mine), where loom helped me to find that issue.
Co-authored-by: dswij <[email protected]>
Recreated the PR as #108. Sorry for the confusion @seanmonstar and @dswij . Github does say the vague "bad things will happen" msg when deleting repo, but might be more useful if it can actually say that only and with specifics. As I didn't realise this PR was still attached to that repo. Thought it was a fork from an older idea. |
Closes #2862
Adds a
GracefulShutdown
utility which: