Description
Trying gopherjs with mqtt/websocket in both Chrome and Firefox as in this branch: https://github.com/Bluebugs/paho.mqtt.golang/tree/bugs/gopherjs-deadlock lead to a deadlock in the following function: https://github.com/Bluebugs/paho.mqtt.golang/blob/bugs/gopherjs-deadlock/token.go#L101 when called from https://github.com/Bluebugs/paho.mqtt.golang/blob/bugs/gopherjs-deadlock/net.go#L216 .
I tried to write a test that would trigger the problem, but couldn't figure out a way for gopherjs test to execute it as it seems some syscall are missing in that case when doing websocket related traffic.
Instead I added a small example in cmd/websocket that work fine with go run or inside a browser with go wasm target, but fail with gopherjs serve and endup in a dead lock. It use mosquitto public mqtt server which provide websocket interface.
A working output would look like:
[client] Connect()
[store] memorystore initialized
[client] about to write new connect msg
[client] socket connected to broker
[client] Using MQTT 3.1.1 protocol
[net] connect started
[net] received connack
[client] startCommsWorkers called
[client] client is connected/reconnected
[net] incoming started
[net] startIncomingComms started
[net] outgoing started
[net] startComms started
[client] startCommsWorkers done
[pinger] keepalive starting
[net] outgoing waiting for an outbound message
[client] exit startClient
[client] enter Subscribe
[net] logic waiting for msg on ibound
[net] startIncomingComms: inboundFromStore complete
[net] logic waiting for msg on ibound
[client] SUBSCRIBE: dup: false qos: 1 retain: false rLength: 0 MessageID: 1 topics: [gopherjs/tests/attributes]
[client] sending subscribe message, topic: gopherjs/tests/attributes
[net] obound priority msg to write, type *packets.SubscribePacket
[client] exit Subscribe
[net] outgoing waiting for an outbound message
[net] startIncoming Received Message
[net] startIncomingComms: got msg on ibound
[net] startIncomingComms: received suback, id: 1
[net] startIncomingComms: granted qoss [1]
[net] logic waiting for msg on ibound
[client] enter Publish
[client] sending publish message, topic: gopherjs/tests/attributes
[net] obound msg to write 2
[net] obound wrote msg, id: 2
[net] outgoing waiting for an outbound message
[net] startIncoming Received Message
[net] startIncomingComms: got msg on ibound
[net] startIncomingComms: received publish, msgId: 1
[net] logic waiting for msg on ibound
[client] enter Unsubscribe
[client] sending unsubscribe message, topics: [gopherjs/tests/attributes]
[client] exit Unsubscribe
[net] putting puback msg on obound
[store] memorystore del: message 1 was deleted
[net] done putting puback msg on obound
[net] obound priority msg to write, type *packets.UnsubscribePacket
[net] outgoing waiting for an outbound message
[net] obound priority msg to write, type *packets.PubackPacket
[net] outgoing waiting for an outbound message
[net] startIncoming Received Message
[net] startIncomingComms: got msg on ibound
[store] memorystore del: message 2 was deleted
[net] startIncomingComms: received puback, id: 2
[net] logic waiting for msg on ibound
While a non working one will look like :
[client] Connect()
[store] memorystore initialized
[client] about to write new connect msg
[client] socket connected to broker
[client] Using MQTT 3.1.1 protocol
[net] connect started
[net] received connack
[client] startCommsWorkers called
[client] client is connected/reconnected
[net] incoming started
[net] startIncomingComms started
[net] outgoing started
[net] startComms started
[client] startCommsWorkers done
[client] exit startClient
[pinger] keepalive starting
[net] logic waiting for msg on ibound
[net] startIncomingComms: inboundFromStore complete
[net] logic waiting for msg on ibound
[net] outgoing waiting for an outbound message
[client] enter Subscribe
[client] SUBSCRIBE: dup: false qos: 1 retain: false rLength: 0 MessageID: 1 topics: [gopherjs/tests/attributes]
[client] sending subscribe message, topic: gopherjs/tests/attributes
[client] exit Subscribe
[net] obound priority msg to write, type *packets.SubscribePacket
[net] outgoing waiting for an outbound message
[net] startIncoming Received Message
[net] startIncomingComms: got msg on ibound
[net] startIncomingComms: received suback, id: 1
[net] startIncomingComms: granted qoss [1]
[client] enter Publish
[client] sending publish message, topic: gopherjs/tests/attributes
[net] obound msg to write 2
[net] obound wrote msg, id: 2
[net] outgoing waiting for an outbound message
[net] startIncoming Received Message
[pinger] ping check 4.822
[pinger] ping check 9.822
[pinger] ping check 14.821
[pinger] ping check 19.819
[pinger] ping check 24.819
As you can see in the non working case, it never go into [net] logic waiting for msg on ibound
after [net] startIncomingComms: granted qoss [1]
.