-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Transport:Waiting for go routines to exit before closing transport #7666
base: master
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #7666 +/- ##
==========================================
- Coverage 81.86% 81.75% -0.11%
==========================================
Files 361 361
Lines 27821 27838 +17
==========================================
- Hits 22775 22760 -15
- Misses 3847 3871 +24
- Partials 1199 1207 +8
|
for ac := range conns { | ||
ac.tearDown(ErrClientConnClosing) | ||
wg.Add(1) |
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 there any motivation behind replacing the tear down process with goroutines with sync.WaitGroup
? Is this tearDown going to be heavy ops, if not i feel earlier approach might be better? WDYT?
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.
This change was suggested by Doug, because now we wait for all go routines inside transport to exit, so it will take time if we serially wait for all transports to close. So we changed it to do the following:
-we will instruct all transports to close simultaneously
- All the transports will wait for all go routines inside it to exit
- we wait for all transports to close before exiting
Instead for asking each transport to close serially , as other transport might not even be signaled to close until all resources in previous transport are cleaned up. Since the transports are not dependent on each other, this approach saves time.
defer func() { | ||
close(t.readerDone) | ||
if errClose != nil { | ||
t.Close(errClose) |
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.
Won't we end up calling t.Close() multiple times in this case? One another instance where we are calling t.Close is this. Thoughts?
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 I think t.Close()
might be called multiple times but it will execute only once always becuase we check the state of the transport beofre actually executing anything, look here ,
grpc-go/internal/transport/http2_client.go
Line 991 in bcf9171
if t.state == closing { |
And also,
t.Close
was already being called inside the reader
go routine , I just changed it to specifically be called only after the t,readerDone
channel is closed, or it was going into infinite wait.
Fixes: #2869
Previously,
clientconn.Close()
did not guarantee termination of some go routines upon return.Now,
clientconn.Close()
ensures that:readerDone
channel to signal completion ofreader
go routine.keepAliveDone
channel to signal completion ofkeepAlive
go routine.clientconn.Close()
waits for all transports to be closed before returning.RELEASE NOTES:
clientconn.Close()
waits for all transports to be closed before returning.