diff --git a/util.go b/util.go index 957f30187..e9ae46b2b 100644 --- a/util.go +++ b/util.go @@ -123,3 +123,19 @@ func iconURL(iconHash, staticIconURL, animatedIconURL, size string) string { } return URL } + +func runGoroutineWithRecover(f func(), recoverHandler func(interface{}), rerun bool) { + go func() { + defer func() { + if err := recover(); err != nil { + if recoverHandler != nil { + recoverHandler(err) + } + if rerun { + runGoroutineWithRecover(f, recoverHandler, rerun) + } + } + }() + f() + }() +} diff --git a/wsapi.go b/wsapi.go index d101c542a..f166472a4 100644 --- a/wsapi.go +++ b/wsapi.go @@ -198,8 +198,22 @@ func (s *Session) Open() error { s.listening = make(chan interface{}) // Start sending heartbeats and reading messages from Discord. - go s.heartbeat(s.wsConn, s.listening, h.HeartbeatInterval) - go s.listen(s.wsConn, s.listening) + runGoroutineWithRecover( + func() { + s.heartbeat(s.wsConn, s.listening, h.HeartbeatInterval) + }, + func(i interface{}) { + s.log(LogError, "recover panic in heartbeat: %v", i) + }, + true) + runGoroutineWithRecover( + func() { + s.listen(s.wsConn, s.listening) + }, + func(i interface{}) { + s.log(LogError, "recover panic in listen: %v", i) + }, + true) s.log(LogInformational, "exiting") return nil @@ -697,10 +711,10 @@ type voiceChannelJoinOp struct { // ChannelVoiceJoin joins the session user to a voice channel. // -// gID : Guild ID of the channel to join. -// cID : Channel ID of the channel to join. -// mute : If true, you will be set to muted upon joining. -// deaf : If true, you will be set to deafened upon joining. +// gID : Guild ID of the channel to join. +// cID : Channel ID of the channel to join. +// mute : If true, you will be set to muted upon joining. +// deaf : If true, you will be set to deafened upon joining. func (s *Session) ChannelVoiceJoin(gID, cID string, mute, deaf bool) (voice *VoiceConnection, err error) { s.log(LogInformational, "called") @@ -744,10 +758,10 @@ func (s *Session) ChannelVoiceJoin(gID, cID string, mute, deaf bool) (voice *Voi // // This should only be used when the VoiceServerUpdate will be intercepted and used elsewhere. // -// gID : Guild ID of the channel to join. -// cID : Channel ID of the channel to join, leave empty to disconnect. -// mute : If true, you will be set to muted upon joining. -// deaf : If true, you will be set to deafened upon joining. +// gID : Guild ID of the channel to join. +// cID : Channel ID of the channel to join, leave empty to disconnect. +// mute : If true, you will be set to muted upon joining. +// deaf : If true, you will be set to deafened upon joining. func (s *Session) ChannelVoiceJoinManual(gID, cID string, mute, deaf bool) (err error) { s.log(LogInformational, "called")