From 91ee92e9d52d90d39b10ac035e24ec152246744c Mon Sep 17 00:00:00 2001 From: diamondburned Date: Sat, 17 Oct 2020 03:21:23 -0700 Subject: [PATCH] Gateway: Fixed a race condition on ReconnectOP --- gateway/op.go | 17 +++++++++-------- utils/wsutil/heart.go | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/gateway/op.go b/gateway/op.go index e5d5b45..954e2b2 100644 --- a/gateway/op.go +++ b/gateway/op.go @@ -30,6 +30,11 @@ const ( GuildSubscriptionsOP OPCode = 14 ) +// ErrReconnectRequest is returned by HandleOP if a ReconnectOP is given. This +// is used mostly internally to signal the heartbeat loop to reconnect, if +// needed. It is not a fatal error. +var ErrReconnectRequest = errors.New("ReconnectOP received") + func (g *Gateway) HandleOP(op *wsutil.OP) error { switch op.Code { case HeartbeatAckOP: @@ -47,13 +52,9 @@ func (g *Gateway) HandleOP(op *wsutil.OP) error { // Server requests to reconnect, die and retry. wsutil.WSDebug("ReconnectOP received.") - // We must reconnect in another goroutine, as running Reconnect - // synchronously would prevent the main event loop from exiting. - go g.Reconnect() - - // Gracefully exit with a nil let the event handler take the signal from - // the pacemaker. - return nil + // Exit with the ReconnectOP error to force the heartbeat event loop to + // reconnect synchronously. Not really a fatal error. + return ErrReconnectRequest case InvalidSessionOP: // Discord expects us to sleep for no reason @@ -101,7 +102,7 @@ func (g *Gateway) HandleOP(op *wsutil.OP) error { g.SessionID = ev.SessionID } - // Throw the event into a channel, it's valid now. + // Throw the event into a channel; it's valid now. g.Events <- ev return nil diff --git a/utils/wsutil/heart.go b/utils/wsutil/heart.go index e4d9f69..6fc1ec0 100644 --- a/utils/wsutil/heart.go +++ b/utils/wsutil/heart.go @@ -108,7 +108,7 @@ func (p *PacemakerLoop) startLoop() error { // Handle the event if err := p.handler(o); err != nil { - p.errorLog(errors.Wrap(err, "handler failed")) + return errors.Wrap(err, "handler failed") } } }