From e84ea0207d21e3d0dfae9377bb56f1b1b3a878e9 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Fri, 17 Mar 2023 09:57:41 +0300 Subject: [PATCH] actor: don't close already closed channel, fix #2932 Waiter should close its channels, but WSClient can also do that and it can do that in a drain loop as well. --- pkg/rpcclient/actor/waiter.go | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/pkg/rpcclient/actor/waiter.go b/pkg/rpcclient/actor/waiter.go index 6804aae18..8de06a6a8 100644 --- a/pkg/rpcclient/actor/waiter.go +++ b/pkg/rpcclient/actor/waiter.go @@ -290,6 +290,8 @@ func (w *EventWaiter) WaitAny(ctx context.Context, vub uint32, hashes ...util.Ui case _, ok := <-bRcvr: if !ok { // We're toast, retry with non-ws client. + bRcvr = nil + aerRcvr = nil wsWaitErr = ErrMissedEvent break } @@ -297,6 +299,8 @@ func (w *EventWaiter) WaitAny(ctx context.Context, vub uint32, hashes ...util.Ui case aer, ok := <-aerRcvr: if !ok { // We're toast, retry with non-ws client. + bRcvr = nil + aerRcvr = nil wsWaitErr = ErrMissedEvent break } @@ -314,8 +318,16 @@ func (w *EventWaiter) WaitAny(ctx context.Context, vub uint32, hashes ...util.Ui drainLoop: for { select { - case <-bRcvr: - case <-aerRcvr: + case _, ok := <-bRcvr: + if !ok { // Missed event means both channels are closed. + bRcvr = nil + aerRcvr = nil + } + case _, ok := <-aerRcvr: + if !ok { // Missed event means both channels are closed. + bRcvr = nil + aerRcvr = nil + } case unsubErr := <-unsubErrs: if unsubErr != nil { errFmt := "unsubscription error: %v" @@ -334,8 +346,10 @@ func (w *EventWaiter) WaitAny(ctx context.Context, vub uint32, hashes ...util.Ui } } } - if wsWaitErr == nil || !errors.Is(wsWaitErr, ErrMissedEvent) { + if bRcvr != nil { close(bRcvr) + } + if aerRcvr != nil { close(aerRcvr) } close(unsubErrs)