-
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
Rare occurences of panic: send on closed channel in rpc/subscription.go #22322
Comments
panic: send on closed channel
in rpc/subscription.go- Attempt to fix ethereum#22322
I have checked this issue for quite a while today. I'm not sure how this case can occur, unless There is only one write to the @samsondav did this issue occur only once, or do you have a way to reproduce it? |
Damn, I just now realize that this panic is not related to |
This fixes a rare issue where the client subscription forwarding loop would attempt send on the subscription's channel after Unsubscribe has returned, leading to a panic if the subscription channel was already closed by the user. Example: sub, _ := client.Subscribe(..., channel, ...) sub.Unsubscribe() close(channel) The race occurred because Unsubscribe called quitWithServer to tell the forwarding loop to stop sending on sub.channel, but did not wait for the loop to actually come down. This is fixed by adding an additional channel to track the shutdown, on which Unsubscribe now waits. Fixes #22322
@samsondav thanks for reporting, @fjl thanks for fixing. For future posterity, we have encountered a deadlock (not a panic) which #22597 has fixed, where:
Documenting here in case it comes up in the future. We have seen increased read errors of the form |
Very good to hear it fixed another problem as well. |
…m#22597) This fixes a rare issue where the client subscription forwarding loop would attempt send on the subscription's channel after Unsubscribe has returned, leading to a panic if the subscription channel was already closed by the user. Example: sub, _ := client.Subscribe(..., channel, ...) sub.Unsubscribe() close(channel) The race occurred because Unsubscribe called quitWithServer to tell the forwarding loop to stop sending on sub.channel, but did not wait for the loop to actually come down. This is fixed by adding an additional channel to track the shutdown, on which Unsubscribe now waits. Fixes ethereum#22322
System information
Geth version:
1.9.25
OS & Version: Linux
Expected behaviour
We are calling
rpc.Unsubscribe
like so:I would expect this to always be safe.
Actual behaviour
In very rare cases this can panic with
send on closed channel
. It seems that messages can still be sent on the passed in channel even afterUnsubscribe
returns.We found this while load testing with fast resubscribes and hundreds of thousands of iterations.
Steps to reproduce the behaviour
Almost impossible to reproduce. Extremely high rates of subscribe/unsubscribe with channel close as detailed above might expose it.
Backtrace
Probable cause and suggested fix
It seems that
quitWithError
(go-ethereum/rpc/subscription.go
Line 251 in 231040c
forward
(go-ethereum/rpc/subscription.go
Line 282 in 231040c
Unsubscribe
returns.A coordination channel so that
quitWithError
waits untilforward
has executed could resolve it.The text was updated successfully, but these errors were encountered: