Skip to content
This repository has been archived by the owner on Jul 11, 2024. It is now read-only.

SIGSEGV panic when a voice reconnect is triggered #298

Closed
goddtriffin opened this issue May 27, 2020 · 15 comments
Closed

SIGSEGV panic when a voice reconnect is triggered #298

goddtriffin opened this issue May 27, 2020 · 15 comments
Assignees

Comments

@goddtriffin
Copy link

Describe the bug
I have written a bot to listen for a single command, connect to a voice channel, 'speak' into it, then leave. This is identical code to this repo's Connecting to Voice example (only this time with real error handling. Everything works fine in a local environment

The bug: When running this in a Docker container on a Digital Ocean droplet, there is a runtime error every single time without fail. I receive this exact error a few times during local development too, but very infrequently. In the production environment, it crashes everytime.

Expected behavior
I expect to listen for a command, and send the single .dca audio through to a voice channel. Simple, just like the Connecting to Voice example.

Error messages

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x7e4f41]

goroutine 40 [running]:
github.com/andersfylling/disgord.(*voiceRepository).VoiceConnectOptions(0xc00000ca00, 0x7c3a16e2a840002, 0x7c3a16e58c20003, 0x0, 0x0, 0x0, 0x0, 0x0)
	/go/pkg/mod/github.com/andersfylling/disgord@v0.17.1/voiceconnection.go:187 +0x731
github.com/andersfylling/disgord.(*voiceRepository).VoiceConnect(0xc00000ca00, 0x7c3a16e2a840002, 0x7c3a16e58c20003, 0x0, 0x0, 0x0, 0x0)
	/go/pkg/mod/github.com/andersfylling/disgord@v0.17.1/voiceconnection.go:86 +0x46
main.(*ZahtBot).zaht(0xc00000ca20, 0x9ca660, 0xc0000d2000, 0xc00014b740)
	/ZahtBot/cmd/bot/zahtbot.go:63 +0xbc
main.(*ZahtBot).mux(...)
	/ZahtBot/cmd/bot/zahtbot.go:56
github.com/andersfylling/disgord.(*dispatcher).trigger(0xc00007c7c0, 0x86d7c0, 0xc00004b510, 0x8b7d60, 0xc00014b740)
	/go/pkg/mod/github.com/andersfylling/disgord@v0.17.1/reactor_gen.go:467 +0x4d8
github.com/andersfylling/disgord.(*dispatcher).dispatch(0xc00007c7c0, 0x9bd2c0, 0xc000022030, 0xc0001d2180, 0xe, 0x8b7d60, 0xc00014b740)
	/go/pkg/mod/github.com/andersfylling/disgord@v0.17.1/reactor.go:154 +0x31f
created by github.com/andersfylling/disgord.demultiplexer
	/go/pkg/mod/github.com/andersfylling/disgord@v0.17.1/reactor.go:76 +0x274

Desktop (please complete the following information):

  • Golang version: v1.14.3
  • Using Go modules? yes
  • Disgord version? v0.17.1
  • Connected to the gateway before using REST methods? N/A (I don't believe I'm using any REST methods... correct me if I'm wrong)

Additional context
Here is the relevant code. This should be identical to this repo's Connecting to Voice example, only this time with error handling.

func (zb *ZahtBot) zaht(session disgord.Session, m *disgord.MessageCreate) {
	log.Println("Zahting...")

        // the line below this comment is where my code is crashing
	voice, err := session.VoiceConnect(m.Message.GuildID, hardcodedChannelID)
	if err != nil {
		log.Printf("Voice Connect error: %+v\n", err)
		return
	}
	defer voice.Close()

	err = voice.StartSpeaking()
	if err != nil {
		log.Printf("Start Speaking error: %+v\n", err)
		return
	}

	err = voice.SendDCA(bytes.NewReader(zb.dca))
	if err != nil {
		log.Printf("Send DCA error: %+v\n", err)
		return
	}

	err = voice.StopSpeaking()
	if err != nil {
		log.Printf("Stop Speaking error: %+v\n", err)
		return
	}

	log.Println("Zahted!")
}
@andersfylling
Copy link
Owner

andersfylling commented May 28, 2020

Right off the bat, this is not the same. It's similar but you call close as soon as possible. I would suggest you debug it to see if the close is what causing the issue.

First off, Discord states that the guild id is optional. So if someone sends your bot a DM, there won't be a guild ID. that would definitely cause an error here. I'd suggest injecting a middleware that filters out DM messages.

Note that keeping the guild id dynamic, while the channel id is hardcoded causes some concern.

@andersfylling
Copy link
Owner

andersfylling commented May 28, 2020

If I run this:

type ZahtBot struct {

}

func (zb *ZahtBot) zaht(session disgord.Session, m *disgord.MessageCreate) {
	log.Println("Zahting...")

	// the line below this comment is where my code is crashing
	voice, err := session.VoiceConnect(m.Message.GuildID, 673893473409171477)
	if err != nil {
		log.Printf("Voice Connect error: %+v\n", err)
		return
	}
	defer voice.Close()

	err = voice.StartSpeaking()
	if err != nil {
		log.Printf("Start Speaking error: %+v\n", err)
		return
	}

	f, _ := os.Open("test.dca")
	defer f.Close()

	err = voice.SendDCA(f)
	if err != nil {
		log.Printf("Send DCA error: %+v\n", err)
		return
	}

	err = voice.StopSpeaking()
	if err != nil {
		log.Printf("Stop Speaking error: %+v\n", err)
		return
	}

	log.Println("Zahted!")
}

the bot plays the sound, no issue. However, after the file has been transmitted, I get the following:

INFO[0008] Zahted!                                      
DEBU[0008] [ws-v,s:15,shard:0]closing operations handler 
ERRO[0008] [ws-v,s:18,shard:0]failed to write: failed to write data frame: websocket closed: sent close: status = StatusNormalClosure and reason = "Bot is shutting down"{5 0xc000018d60 VOICE_SPEAKING} 
DEBU[0008] [ws-v,s:19,shard:0]closing receiver          
DEBU[0008] [ws-v,s:17,shard:0]stopping pulse            
DEBU[0008] [ws-v,s:20,shard:0]closing emitter after write error 
DEBU[0008] [ws-v,s:21,shard:0]is reconnecting           
INFO[0008] [ws-v,s:22,shard:0]disconnected              
DEBU[0008] [ws-v,s:23,shard:0]already disconnected

This error can be ignored, although ugly and should be patched. But your bot will still be functional.

@andersfylling
Copy link
Owner

I can also say that I tried the following:

go build .
./bot

And then I spammed the text channels with new messages. I still was not able to get this error.

@andersfylling
Copy link
Owner

andersfylling commented May 28, 2020

The code can also be reduced to:

func (zb *ZahtBot) zaht(session disgord.Session, m *disgord.MessageCreate) {
	log.Println("Zahting...")

        // the line below this comment is where my code is crashing
	voice, err := session.VoiceConnect(m.Message.GuildID, hardcodedChannelID)
	if err != nil {
		log.Printf("Voice Connect error: %+v\n", err)
		return
	}
	defer voice.Close()
	log.Println("SUCCESS")
}

Since there is a panic here, I'm really curious if you can fix up the variables. Use a hardcoded guild id and hardcoded channel id. Make sure they are correct. That removes another set of possibilities.

Edit: it's unrelated.

@andersfylling andersfylling changed the title Bug: VoiceConnect always crashes when ran inside Docker container on DigitalOcean droplet VoiceConnect always crashes when ran inside Docker container on DigitalOcean droplet May 28, 2020
@andersfylling
Copy link
Owner

Another person in Discord stated a similar issue. After reviewing his logs, I noticed it always happened after a reconnect took place.

This issue is missing logs so I can't figure out if it's the same situation. Given that it happens every time, I'm feeling uncertain if it's related.

Can you give more insight on the following:

  1. do you have logs? Not just the stack trace of the error
  2. does it happen instantly or eventually?
  3. do you see the bot pop up in the voice channel before it crashes, or does it fail to pop up at all?

@goddtriffin
Copy link
Author

First off thanks for the insight.

In reference to the dynamic Guild ID and the static channel ID, I'm waiting to figure out how to retrieve the voice channel that the message sender is in (if they are in one). I don't believe there is a way to do that in this library yet, so that's why I created issue #288. Before this bot goes public, I will either have to figure it out or submit a PR against this (amazing) library.

You can view my bot code here. This way you can test my exact environment if you wanted, because it seems like you aren't able to replicate the bug.

I will be posting better logs in a moment.

@goddtriffin
Copy link
Author

Here are some logs that show a crash that happens when the bot is spammed. You can tell when the bot starts and stops voice-ing by the 'Zahting...' and 'Zahted!' log lines. In this log dump, the bot successfully zaht's once, then crashes on the second time.

2020/05/28 12:41:45 Zahting...
{"level":"debug","msg":"[ws-v,s:1,shard:0]starting receiver","time":"2020-05-28T12:41:45-05:00"}
{"level":"debug","msg":"[ws-v,s:2,shard:0]Ready to receive operation codes...","time":"2020-05-28T12:41:45-05:00"}
{"level":"debug","msg":"[ws-v,s:4,shard:0]heartbeat ACK ok","time":"2020-05-28T12:41:45-05:00"}
{"level":"debug","msg":"[ws-v,s:5,shard:0]sent heartbeat","time":"2020-05-28T12:41:45-05:00"}
{"level":"debug","msg":"[ws-v,s:3,shard:0]starting emitter","time":"2020-05-28T12:41:45-05:00"}
{"level":"info","msg":"[ws-v,s:6,shard:0]connected","time":"2020-05-28T12:41:45-05:00"}
{"level":"debug","msg":"[ws-v,s:7,shard:0]tried calling undefined discord operation5","time":"2020-05-28T12:41:45-05:00"}
{"level":"debug","msg":"[ws-v,s:8,shard:0]tried calling undefined discord operation5","time":"2020-05-28T12:41:48-05:00"}
2020/05/28 12:41:48 Zahted!
{"level":"debug","msg":"[ws-v,s:9,shard:0]closing operations handler","time":"2020-05-28T12:41:48-05:00"}
{"level":"debug","msg":"[ws-v,s:10,shard:0]stopping pulse","time":"2020-05-28T12:41:48-05:00"}
{"level":"debug","msg":"[ws-v,s:11,shard:0]closing emitter","time":"2020-05-28T12:41:48-05:00"}
{"level":"debug","msg":"[ws-v,s:12,shard:0]failed to get reader: context canceled","time":"2020-05-28T12:41:48-05:00"}
{"level":"debug","msg":"[ws-v,s:13,shard:0]closing receiver","time":"2020-05-28T12:41:48-05:00"}
{"level":"info","msg":"[ws-v,s:14,shard:0]disconnected","time":"2020-05-28T12:41:48-05:00"}
2020/05/28 12:41:48 Zahting...
{"level":"debug","msg":"[ws-v,s:1,shard:0]starting receiver","time":"2020-05-28T12:41:49-05:00"}
{"level":"debug","msg":"[ws-v,s:2,shard:0]starting emitter","time":"2020-05-28T12:41:49-05:00"}
{"level":"debug","msg":"[ws-v,s:3,shard:0]Ready to receive operation codes...","time":"2020-05-28T12:41:49-05:00"}
{"level":"debug","msg":"[ws-v,s:4,shard:0]heartbeat ACK ok","time":"2020-05-28T12:41:49-05:00"}
{"level":"debug","msg":"[ws-v,s:5,shard:0]sent heartbeat","time":"2020-05-28T12:41:49-05:00"}
{"level":"debug","msg":"[ws-v,s:6,shard:0]closing receiver after read error","time":"2020-05-28T12:41:49-05:00"}
{"level":"debug","msg":"[ws-v,s:7,shard:0]is reconnecting","time":"2020-05-28T12:41:49-05:00"}
{"level":"debug","msg":"[ws-v,s:8,shard:0]trying to connect","time":"2020-05-28T12:41:49-05:00"}
{"level":"debug","msg":"[ws-v,s:9,shard:0]stopping pulse","time":"2020-05-28T12:41:49-05:00"}
{"level":"debug","msg":"[ws-v,s:10,shard:0]closing emitter","time":"2020-05-28T12:41:49-05:00"}
{"level":"debug","msg":"[ws-v,s:11,shard:0]closing operations handler","time":"2020-05-28T12:41:49-05:00"}
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x13f40f1]

goroutine 197 [running]:
github.com/andersfylling/disgord.(*voiceRepository).VoiceConnectOptions(0xc00011aa40, 0x7c3a16e2a840002, 0x7c3a16e58c20003, 0x0, 0x0, 0x0, 0x0, 0x0)
	/Users/toddeverettgriffin/go/pkg/mod/github.com/andersfylling/disgord@v0.17.1/voiceconnection.go:187 +0x731
github.com/andersfylling/disgord.(*voiceRepository).VoiceConnect(0xc00011aa40, 0x7c3a16e2a840002, 0x7c3a16e58c20003, 0x0, 0x0, 0x0, 0x0)
	/Users/toddeverettgriffin/go/pkg/mod/github.com/andersfylling/disgord@v0.17.1/voiceconnection.go:86 +0x46
main.(*ZahtBot).zaht(0xc00011aa60, 0x15e0a40, 0xc000184000, 0xc000374280)
	/Users/toddeverettgriffin/Documents/code/ZahtBot/cmd/bot/zahtbot.go:63 +0xbc
main.(*ZahtBot).mux(...)
	/Users/toddeverettgriffin/Documents/code/ZahtBot/cmd/bot/zahtbot.go:56
github.com/andersfylling/disgord.(*dispatcher).trigger(0xc0001067c0, 0x147db80, 0xc000109430, 0x14c8fa0, 0xc000374280)
	/Users/toddeverettgriffin/go/pkg/mod/github.com/andersfylling/disgord@v0.17.1/reactor_gen.go:467 +0x4d8
github.com/andersfylling/disgord.(*dispatcher).dispatch(0xc0001067c0, 0x15d3380, 0xc0000220a0, 0xc000248640, 0xe, 0x14c8fa0, 0xc000374280)
	/Users/toddeverettgriffin/go/pkg/mod/github.com/andersfylling/disgord@v0.17.1/reactor.go:154 +0x31f
created by github.com/andersfylling/disgord.demultiplexer
	/Users/toddeverettgriffin/go/pkg/mod/github.com/andersfylling/disgord@v0.17.1/reactor.go:76 +0x274
make: *** [runlocal] Error 2

@andersfylling
Copy link
Owner

Okay, I see it's related to the reconnect.

Is this because you keep forcing the bot to connect to a already connected voice channel?

@andersfylling andersfylling changed the title VoiceConnect always crashes when ran inside Docker container on DigitalOcean droplet Bot crashes when a voice reconnect is triggered May 28, 2020
@andersfylling andersfylling changed the title Bot crashes when a voice reconnect is triggered SIGSEGV panic when a voice reconnect is triggered May 28, 2020
@goddtriffin
Copy link
Author

Here is the log dump from the Docker container + DigitalOcean droplet:

{"level":"info","msg":"Connecting to discord Gateway","time":"2020-05-28T17:55:05Z"}
{"level":"debug","msg":"[ws-e,s:1,shard:0]trying to connect","time":"2020-05-28T17:55:05Z"}
{"level":"debug","msg":"[shardSync]shard0is waiting to identify","time":"2020-05-28T17:55:05Z"}
{"level":"debug","msg":"[ws-e,s:2,shard:0]waiting to send identify/resume","time":"2020-05-28T17:55:05Z"}
{"level":"debug","msg":"[ws-e,s:3,shard:0]starting receiver","time":"2020-05-28T17:55:05Z"}
{"level":"debug","msg":"[ws-e,s:4,shard:0]starting emitter","time":"2020-05-28T17:55:05Z"}
{"level":"debug","msg":"[ws-e,s:5,shard:0]Ready to receive operation codes...","time":"2020-05-28T17:55:05Z"}
{"level":"debug","msg":"[ws-e,s:6,shard:0]sendIdentityPacket is acquiring once channel","time":"2020-05-28T17:55:05Z"}
{"level":"debug","msg":"[ws-e,s:7,shard:0]writing to once channel0xc000181ce0","time":"2020-05-28T17:55:05Z"}
{"level":"debug","msg":"[ws-e,s:8,shard:0]finished writing to once channel0xc000181ce0","time":"2020-05-28T17:55:05Z"}
{"level":"debug","msg":"[ws-e,s:9,shard:0]sent identify/resume","time":"2020-05-28T17:55:05Z"}
{"level":"debug","msg":"[shardSync]shard0waited and finished execution after226.400363ms","time":"2020-05-28T17:55:05Z"}
{"level":"debug","msg":"[ws-e,s:10,shard:0]establishing connection succeeded","time":"2020-05-28T17:55:05Z"}
{"level":"info","msg":"Connected","time":"2020-05-28T17:55:05Z"}
{"level":"debug","msg":"[ws-e,s:11,shard:0]heartbeat ACK ok","time":"2020-05-28T17:55:05Z"}
{"level":"debug","msg":"[ws-e,s:12,shard:0]sent heartbeat","time":"2020-05-28T17:55:05Z"}
2020/05/28 17:55:05 ZahtBot is online!
2020/05/28 17:55:34 Zahting...
{"level":"debug","msg":"[ws-v,s:1,shard:0]starting receiver","time":"2020-05-28T17:55:35Z"}
{"level":"debug","msg":"[ws-v,s:2,shard:0]starting emitter","time":"2020-05-28T17:55:35Z"}
{"level":"debug","msg":"[ws-v,s:3,shard:0]Ready to receive operation codes...","time":"2020-05-28T17:55:35Z"}
{"level":"debug","msg":"[ws-v,s:4,shard:0]heartbeat ACK ok","time":"2020-05-28T17:55:35Z"}
{"level":"debug","msg":"[ws-v,s:5,shard:0]sent heartbeat","time":"2020-05-28T17:55:35Z"}
{"level":"debug","msg":"[ws-v,s:6,shard:0]closing receiver after read error","time":"2020-05-28T17:55:35Z"}
{"level":"debug","msg":"[ws-v,s:7,shard:0]is reconnecting","time":"2020-05-28T17:55:35Z"}
{"level":"debug","msg":"[ws-v,s:8,shard:0]trying to connect","time":"2020-05-28T17:55:35Z"}
{"level":"debug","msg":"[ws-v,s:9,shard:0]closing emitter","time":"2020-05-28T17:55:35Z"}
{"level":"debug","msg":"[ws-v,s:10,shard:0]closing operations handler","time":"2020-05-28T17:55:35Z"}
{"level":"debug","msg":"[ws-v,s:11,shard:0]stopping pulse","time":"2020-05-28T17:55:35Z"}
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x7e4f41]

goroutine 43 [running]:
github.com/andersfylling/disgord.(*voiceRepository).VoiceConnectOptions(0xc00000ca00, 0x7c3a16e2a840002, 0x7c3a16e58c20003, 0x0, 0x0, 0x0, 0x0, 0x0)
	/go/pkg/mod/github.com/andersfylling/disgord@v0.17.1/voiceconnection.go:187 +0x731
github.com/andersfylling/disgord.(*voiceRepository).VoiceConnect(0xc00000ca00, 0x7c3a16e2a840002, 0x7c3a16e58c20003, 0x0, 0x0, 0x0, 0x0)
	/go/pkg/mod/github.com/andersfylling/disgord@v0.17.1/voiceconnection.go:86 +0x46
main.(*ZahtBot).zaht(0xc00000ca20, 0x9ca660, 0xc0000d2000, 0xc000222320)
	/ZahtBot/cmd/bot/zahtbot.go:63 +0xbc
main.(*ZahtBot).mux(...)
	/ZahtBot/cmd/bot/zahtbot.go:56
github.com/andersfylling/disgord.(*dispatcher).trigger(0xc00007c7c0, 0x86d7c0, 0xc00004b510, 0x8b7d60, 0xc000222320)
	/go/pkg/mod/github.com/andersfylling/disgord@v0.17.1/reactor_gen.go:467 +0x4d8
github.com/andersfylling/disgord.(*dispatcher).dispatch(0xc00007c7c0, 0x9bd2c0, 0xc000022030, 0xc0002002e0, 0xe, 0x8b7d60, 0xc000222320)
	/go/pkg/mod/github.com/andersfylling/disgord@v0.17.1/reactor.go:154 +0x31f
created by github.com/andersfylling/disgord.demultiplexer
	/go/pkg/mod/github.com/andersfylling/disgord@v0.17.1/reactor.go:76 +0x274

@andersfylling
Copy link
Owner

Yeah, that's another reconnect.

@goddtriffin
Copy link
Author

For the Docker+DO issue, I know for a fact that the bot is not connected to anything. There are no current instances in the wild, and I don't spam it while testing. It crashes on the first zaht; it connects, doesn't voice anything, then lingers.

@andersfylling
Copy link
Owner

andersfylling commented May 28, 2020

From the logs we do see that it happens on a reconnect. So I'll restrict this issue to that. Once that is resolved, we can see if there are still any defect behavior in docker.

@oidq
Copy link
Contributor

oidq commented May 29, 2020

I digged a bit in the code and found that for me it happened on closing receiver after read error logged in receiver() in internal/gateway/client.go, which fires c.reconnect() and does c.cancel()
At that time, internalConnect() is in select on line 298 and match case <-ctx.Done(). This case does not set error nor evt so it return nil, nil and VoiceConnectOptions panics to nil pointer dereference on line 187.

my log: https://pastebin.com/1cJhhnXb

oidq added a commit to oidq/disgord that referenced this issue May 30, 2020
* Fix SIGSEGV panic in issue andersfylling#298, function returns non-nil error:
  "context cancelled"

* Fix opCode 3 sending before opCode 0 in voice
	* this caused "authentication error", which resulted in SIGSEGV

* Add & improved errors and logs in (re)connecting functions
oidq added a commit to oidq/disgord that referenced this issue May 30, 2020
* Fix SIGSEGV panic in issue andersfylling#298, function returns non-nil error:
  "context cancelled"

* Fix opCode 3 sending before opCode 0 in voice
	* this caused "authentication error", which resulted in SIGSEGV

* Add & improved errors and logs in (re)connecting functions
oidq added a commit to oidq/disgord that referenced this issue May 30, 2020
* Fix SIGSEGV panic in issue andersfylling#298, function returns non-nil error:
  "context cancelled"

* Fix opCode 3 sending before opCode 0 in voice
	* this caused "authentication error", which resulted in SIGSEGV

* Add & improved errors and logs in (re)connecting functions
oidq added a commit to oidq/disgord that referenced this issue May 30, 2020
* Fix SIGSEGV panic in issue andersfylling#298, function returns non-nil error:
  "context cancelled"

* Fix opCode 3 sending before opCode 0 in voice
	* this caused "authentication error", which resulted in SIGSEGV

* Add & improved errors and logs in (re)connecting functions
oidq added a commit to oidq/disgord that referenced this issue May 30, 2020
* Fix SIGSEGV panic in issue andersfylling#298, function returns non-nil error:
  "context cancelled"

* Fix opCode 3 sending before opCode 0 in voice
	* this caused "authentication error", which resulted in SIGSEGV

* Add & improved errors and logs in (re)connecting functions
@andersfylling
Copy link
Owner

@magnusfrater it seems @oidq have resolved the nil panic. If you can use the latest on the develop branch to further verify this that would be great.

@oidq did mention a new issue though, that instead of the nil panic he sometimes got a auth issue. Regardless, it's a nice improvement and fixes the overall codeflow to be more accurate in accordance with the discord docs.

@andersfylling andersfylling added voice and removed voice labels May 30, 2020
@andersfylling andersfylling added voice and removed voice labels May 30, 2020
@goddtriffin
Copy link
Author

These fixes seem to solve my issue. The only errors that show up now are these:

{"level":"error","msg":"Voice Close error: failed to close WebSocket: failed to write control frame opClose: WebSocket closed: read timed out: context canceled\n","time":"2020-05-30T19:49:40Z"}
{"level":"error","msg":"[ws-v,s:14,shard:0]gateway.clientPacket.Data: disgord.voiceSpeakingData.SSRC: Delay: failed to write: failed to write data frame: failed to write frame: WebSocket closed: read timed out: context canceled{5 0xc0001512e0 VOICE_SPEAKING}","time":"2020-05-30T19:49:40Z"}

But the fix for these might fall under a separate issue.

oidq added a commit to oidq/disgord that referenced this issue May 31, 2020
* fix handling of error in nhooyr websocket wrapper (mentioned in andersfylling#298)
	* closing context given to g.c.Read(ctx) leads to WebSocket being closed
  	  coder/websocket#242
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants