Commit fc9bbf20 authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Don't close writer channel at client shutdown.

Closing the channel could cause a panic if a c.write was pending.
Instead, ensure we send a closeMessage to the writer, and cause the
writer to exit when it receives a closeMessage.
parent dd27cf41
...@@ -676,6 +676,7 @@ func startClient(conn *websocket.Conn) (err error) { ...@@ -676,6 +676,7 @@ func startClient(conn *websocket.Conn) (err error) {
defer func() { defer func() {
if isWSNormalError(err) { if isWSNormalError(err) {
err = nil err = nil
c.close(nil)
} else { } else {
m, e := errorToWSCloseMessage(err) m, e := errorToWSCloseMessage(err)
if m != "" { if m != "" {
...@@ -685,13 +686,8 @@ func startClient(conn *websocket.Conn) (err error) { ...@@ -685,13 +686,8 @@ func startClient(conn *websocket.Conn) (err error) {
Value: m, Value: m,
}) })
} }
select { c.close(e)
case c.writeCh <- closeMessage{e}:
case <-c.writerDone:
}
} }
close(c.writeCh)
c.writeCh = nil
}() }()
c.writerDone = make(chan struct{}) c.writerDone = make(chan struct{})
...@@ -1153,10 +1149,13 @@ func clientWriter(conn *websocket.Conn, ch <-chan interface{}, done chan<- struc ...@@ -1153,10 +1149,13 @@ func clientWriter(conn *websocket.Conn, ch <-chan interface{}, done chan<- struc
return return
} }
case closeMessage: case closeMessage:
err := conn.WriteMessage(websocket.CloseMessage, m.data) if m.data != nil {
if err != nil { conn.WriteMessage(
return websocket.CloseMessage,
m.data,
)
} }
return
default: default:
log.Printf("clientWiter: unexpected message %T", m) log.Printf("clientWiter: unexpected message %T", m)
return return
...@@ -1185,6 +1184,15 @@ func (c *webClient) write(m clientMessage) error { ...@@ -1185,6 +1184,15 @@ func (c *webClient) write(m clientMessage) error {
} }
} }
func (c *webClient) close(data []byte) error {
select {
case c.writeCh <- closeMessage{data}:
return nil
case <-c.writerDone:
return ErrWriterDead
}
}
func (c *webClient) error(err error) error { func (c *webClient) error(err error) error {
switch e := err.(type) { switch e := err.(type) {
case userError: case userError:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment