-
Notifications
You must be signed in to change notification settings - Fork 20.4k
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
event, p2p/simulations/adapters: use buffered channel to avoid goroutine leak #20657
Conversation
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.
Very nice finding!
event/subscription.go
Outdated
@@ -143,7 +143,7 @@ func (s *resubscribeSub) loop() { | |||
} | |||
|
|||
func (s *resubscribeSub) subscribe() Subscription { | |||
subscribed := make(chan error) | |||
subscribed := make(chan error, 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.
I think it would be better to fix this case by waiting on the subscribed
channel when the subscribe
loop exits. This way, Unsubscribe
will block until the goroutine running s.fn
has exited.
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.
Actually, I have now applied the fix myself.
@@ -287,7 +287,7 @@ func (n *ExecNode) Stop() error { | |||
if err := n.Cmd.Process.Signal(syscall.SIGTERM); err != nil { | |||
return n.Cmd.Process.Kill() | |||
} | |||
waitErr := make(chan error) | |||
waitErr := make(chan error, 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.
This fix is OK as-is.
…0657) Co-authored-by: Felix Lange <[email protected]>
subscribe()
in event/subscribe.go andStop()
in p2p/simulations/adapters/exec.go share a same problem: some goroutines in these functions will be leaked in certain cases (unsub forsubscribe()
, and timeout forStop()
).In
subscribe()
, the send operationsubscribed <- err
on L115 will be blocked forever whenunsub
is selected. Thus the child goroutine leaks and always occupies the memory.Adding one buffer to the channel will make the send operation never block the child goroutine,
and it will not change semantic.
The same is true for
Stop()
.In
Stop()
, althoughKill()
is called on timeout,I am not sure if the child goroutine will be in the same process or not. Here is the annotation of
Kill()
, in /os/exec.go: