Websocket not erroring on client disconnect

717 views
Skip to first unread message

Aiden

unread,
Mar 5, 2014, 1:19:01 PM3/5/14
to golan...@googlegroups.com
Hello everyone!

I have a websocket handler (from code.google.com/p/go.net/websocket). Reading around it seems
writing to the socket should return an error if the client disconnects. In my case it doesn't seem to.
My socket backs on to a rabbitmq server, and what I get is tons of stale queues on the server, and
lots of websocket handler routines in go constantly writing to sockets with no browser on the end.

I'm sure it is my mistake, here's some of my handler:

116     msgchan,err := ch.Consume(q.Name, "", true, false, false, false, nil)
117     done := make(chan bool)
118
119     go func(){
120         for d := range msgchan {
121             err = websocket.Message.Send(w,d.Body)
122           
123             if err != nil {
124                 done <- true
125                 return
126             }
127         }
128     }()
129
130     <-done
131     fmt.Printf("Exiting subscriber\n")

My code never reaches the last line, even when the browser closes its websocket by changing URL
or closing tab or whatever.

Any help appriciated :)

Aiden

unread,
Mar 5, 2014, 2:02:37 PM3/5/14
to golan...@googlegroups.com
Changed that, but the error condition on line 123 is never true, so the true is never
sent.

On Wednesday, 5 March 2014 18:25:12 UTC, Islan Dberry wrote:
The goroutine is stuck at 

    124                 done <- true

Use a buffered channel to avoid this issue:

    117     done := make(chan bool, 1)

Aiden

unread,
Mar 5, 2014, 3:20:36 PM3/5/14
to golan...@googlegroups.com
Just tried this: http://godoc.org/github.com/garyburd/go-websocket/ instead of the other websocket lib,
same issue. AFAIK all my handlers are still running after the HTTP connection is closed, which means on the
next message they get they should err and close. I never see my handlers exit, which means they are always
looking for messages from the queue.

Console traces show they continue to try and send messages to non-existent, long disconnected browsers.

On Wednesday, 5 March 2014 19:25:35 UTC, Islan Dberry wrote:
Yeah, my error. The unbuffered channel code is also correct. 

Aiden

unread,
Mar 5, 2014, 4:04:39 PM3/5/14
to golan...@googlegroups.com
My code is sketchy but I worked around it a bit by sending
PING messages every 2 seconds on one channel, and output messages for the websocket on another,
then selecting off each channel.

I then set the timeout on the pings, eventually it seems to kill the polling exiting the HTTP handler
then taking the websocket/AMQP connections down too. Does what I want, but seems a bit like something
the underlying library should be doing?

125     // Start getting messages
126     msgchan,err := ch.Consume(q.Name, "", true, false, false, false, nil)
127
128     done := make(chan bool)
129     outmsg := make(chan []byte)
130     ctrlchan := make(chan bool)
131
132     defer conn.Close()
133
134     go func(){
135         for {
136             select {
137                 case d := <- outmsg:
138                     err := conn.WriteMessage(websocket.TextMessage, []byte(fmt.Sprintf("%s\n",d)))
139                     fmt.Printf("Sent message\n")
140                     if err != nil {
141                         fmt.Printf("Got send error: %s\n",err)
142                         done <- true
143                         return
144                     }
145                 case <- ctrlchan:
146                     fmt.Printf("Pinging\n")
147                     err := conn.WriteControl(websocket.PingMessage, nil, time.Now().Add(100*time.Millisecond))
148                     if err != nil {
149                         // Ping timed out, kill connection
150                         done <- true
151                         return
152                     }
153             }
154         }
155     }()
156    
157     // Pull from AMQP and deliver to websocket output channel
158     go func() {
159         for {
160             d := <- msgchan
161             outmsg <- d.Body
162         }
163     }()
164    
165     // Send control message pings to client every 2 seconds
166     go func() {
167         for {
168             ctrlchan <- true
169             time.Sleep(2 * time.Second)
170         }
171     }()
172     <-done
173     fmt.Printf("Exiting subscriber\n")
174 }

C Banning

unread,
Mar 5, 2014, 6:30:46 PM3/5/14
to golan...@googlegroups.com
try gorilla/websocket as mentioned earlier today here: https://groups.google.com/forum/#!topic/golang-nuts/8D8f-0ubOuo

Aiden

unread,
Mar 6, 2014, 6:45:02 AM3/6/14
to golan...@googlegroups.com
Thanks for the reply guys,

Gary,
I'm using Go 1.2 from the Fedora repos, go get on the net package for websockets (first version).
I'll give Gorilla a go and see if terminated connections exit my loop, though it seems to work OK using the WriteControl
to ping in a goroutine atm, though I did notice it can take up to 30 seconds after closing the browser window to timeout, so
perhaps the browser keeps the socket alive for a bit too.

On Thursday, 6 March 2014 00:35:56 UTC, gary b wrote:
- Use github.com/gorillla/webscoket instead of github.com/garyburd/go-websocket.

- The application should read the connection to handle PINGs sent by the browser and PONGs sent in response to the server's PINGs.

- I cannot reproduce the problem with my test application. What operating system, browser and version of Go are you using?

ma...@nicolasdavies.com.au

unread,
Mar 6, 2014, 4:30:51 PM3/6/14
to golan...@googlegroups.com
Have you had a look at netstat or something to see if the browser has closed the connection?

Or have the ws closed in js and look at the network inspector in chrome?

Also just a side note, you don't check the error at the start, you should define err inside the go routine also because the closure hides from the compiler that you didn't use it

Reply all
Reply to author
Forward
Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted
0 new messages