-
Notifications
You must be signed in to change notification settings - Fork 5.9k
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
executor,server: re-implement the kill
statement by checking the Next()
function
#10841
Conversation
…one` in the `Next()` function
/run-all-tests |
Codecov Report
@@ Coverage Diff @@
## master #10841 +/- ##
===============================================
- Coverage 80.8814% 80.8585% -0.023%
===============================================
Files 419 419
Lines 88668 88661 -7
===============================================
- Hits 71716 71690 -26
- Misses 11726 11742 +16
- Partials 5226 5229 +3 |
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.
In this mechanism, we need to make sure the following rules hold:
context
should be passed from the root executor to the deep leaf executor in the tree.context.Done()
should be checked in every background goroutine for every parallel executor. And once the upper layer callsCancel()
, all the background goroutines should stop.Close()
should be safe to call after the upper layer calledCancel()
.
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.
In this mechanism, we need to make sure the following rules hold:
context
should be passed from the root executor to the deep leaf executor in the tree.context.Done()
should be checked in every background goroutine for every parallel executor. And once the upper layer callsCancel()
, all the background goroutines should stop.Close()
should be safe to call after the upper layer calledCancel()
.
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.
In this mechanism, we need to make sure the following rules hold:
context
should be passed from the root executor to the deep leaf executor in the tree.context.Done()
should be checked in every background goroutine for every parallel executor. And once the upper layer callsCancel()
, all the background goroutines should stop.Close()
should be safe to call after the upper layer calledCancel()
.
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.
In this mechanism, we need to make sure the following rules hold:
context
should be passed from the root executor to the deep leaf executor in the tree.context.Done()
should be checked in every background goroutine for every parallel executor. And once the upper layer callsCancel()
, all the background goroutines should stop.Close()
should be safe to call after the upper layer calledCancel()
.
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.
In this mechanism, we need to make sure the following rules hold:
context
should be passed from the root executor to the deep leaf executor in the tree.context.Done()
should be checked in every background goroutine for every parallel executor. And once the upper layer callsCancel()
, all the background goroutines should stop.Close()
should be safe to call after the upper layer calledCancel()
.
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.
In this mechanism, we need to make sure the following rules hold:
context
should be passed from the root executor to the deep leaf executor in the tree.context.Done()
should be checked in every background goroutine for every parallel executor. And once the upper layer callsCancel()
, all the background goroutines should stop.Close()
should be safe to call after the upper layer calledCancel()
.
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.
In this mechanism, we need to make sure the following rules hold:
context
should be passed from the root executor to the deep leaf executor in the tree.context.Done()
should be checked in every background goroutine for every parallel executor. And once the upper layer callsCancel()
, all the background goroutines should stop.Close()
should be safe to call after the upper layer calledCancel()
.
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.
In this mechanism, we need to make sure the following rules hold:
context
should be passed from the root executor to the deep leaf executor in the tree.context.Done()
should be checked in every background goroutine for every parallel executor. And once the upper layer callsCancel()
, all the background goroutines should stop.Close()
should be safe to call after the upper layer calledCancel()
.
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.
In this mechanism, we need to make sure the following rules hold:
context
should be passed from the root executor to the deep leaf executor in the tree.context.Done()
should be checked in every background goroutine for every parallel executor. And once the upper layer callsCancel()
, all the background goroutines should stop.Close()
should be safe to call after the upper layer calledCancel()
.
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.
In this mechanism, we need to make sure the following rules hold:
context
should be passed from the root executor to the deep leaf executor in the tree.context.Done()
should be checked in every background goroutine for every parallel executor. And once the upper layer callsCancel()
, all the background goroutines should stop.Close()
should be safe to call after the upper layer calledCancel()
.
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.
In this mechanism, we need to make sure the following rules hold:
context
should be passed from the root executor to the deep leaf executor in the tree.context.Done()
should be checked in every background goroutine for every parallel executor. And once the upper layer callsCancel()
, all the background goroutines should stop.Close()
should be safe to call after the upper layer calledCancel()
.
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.
In this mechanism, we need to make sure the following rules hold:
context
should be passed from the root executor to the deep leaf executor in the tree.context.Done()
should be checked in every background goroutine for every parallel executor. And once the upper layer callsCancel()
, all the background goroutines should stop.Close()
should be safe to call after the upper layer calledCancel()
.
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.
In this mechanism, we need to make sure the following rules hold:
context
should be passed from the root executor to the deep leaf executor in the tree.context.Done()
should be checked in every background goroutine for every parallel executor. And once the upper layer callsCancel()
, all the background goroutines should stop.Close()
should be safe to call after the upper layer calledCancel()
.
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.
In this mechanism, we need to make sure the following rules hold:
context
should be passed from the root executor to the deep leaf executor in the tree.context.Done()
should be checked in every background goroutine for every parallel executor. And once the upper layer callsCancel()
, all the background goroutines should stop.Close()
should be safe to call after the upper layer calledCancel()
.
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.
In this mechanism, we need to make sure the following rules hold:
context
should be passed from the root executor to the deep leaf executor in the tree.context.Done()
should be checked in every background goroutine for every parallel executor. And once the upper layer callsCancel()
, all the background goroutines should stop.Close()
should be safe to call after the upper layer calledCancel()
.
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.
In this mechanism, we need to make sure the following rules hold:
context
should be passed from the root executor to the deep leaf executor in the tree.context.Done()
should be checked in every background goroutine for every parallel executor. And once the upper layer callsCancel()
, all the background goroutines should stop.Close()
should be safe to call after the upper layer calledCancel()
.
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.
In this mechanism, we need to make sure the following rules hold:
context
should be passed from the root executor to the deep leaf executor in the tree.context.Done()
should be checked in every background goroutine for every parallel executor. And once the upper layer callsCancel()
, all the background goroutines should stop.Close()
should be safe to call after the upper layer calledCancel()
.
Can we use an atomic variable to determine whether the |
Use many different mechanisms to implement the same thing makes the code less maintainable.
|
No problem... passing context is the golang idiom
I don't mean to check every background goroutine any more. It's impractical as we have proved: difficult to maintain and easy to cause goroutine leak.
Cancel will not cancel the background goroutine now ... it just makes |
@tiancaiamao I mean to set an atomic variable to 1 when killing an executor and check the atomic variable while every iteration. |
I know an atomic variable is more effective, but it's not the only factor we should take into consideration @lonng |
Can we guarantee that after canceling an Executor by this way, the |
there are maybe many duplicated check for example:
check and high frequent select maybe need a benchmark- -? |
kill
statement by checking ctx.Done
in the Next()
functionkill
statement by checking the Next()
function
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.
LGTM
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.
LGTM
What problem does this PR solve?
Re-implement the
kill
statement in a better way.In #9844, the implementation of
kill
is changed to useexecutor.Close
. Some goroutine may be callingexecutor.Next
while another one is calling theexecutor.Close
. It's not thread-safe, and panic sometimes (you can imagine that one of them is usinge.result
while another one sete.result
tonil
).What is changed and how it works?
In this commit, I introduce a
Next()
function that wraps thee.Next()
function, andctx.Done()
is checked in the newNext()
function.In this way, we can make sure
kill
signal could be checked as long asNext()
is called, so we can stop an executor eventually.Check List
Tests
It's not easy to write unit tests for the
kill
statement. I tried to make a 'black hole' table (which generates fake data forever when it's read) to support long-running transactions forkill
, but it involves many more changes and those changes are irrelevant. So I decide to leave tests along until I find some better ways.Code changes
Side effects
Related changes