mirror of
https://github.com/jech/galene.git
synced 2024-11-10 02:35:58 +01:00
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.
This commit is contained in:
parent
dd27cf412c
commit
fc9bbf20ea
1 changed files with 17 additions and 9 deletions
26
webclient.go
26
webclient.go
|
@ -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) {
|
||||||
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
|
||||||
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 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
Loading…
Reference in a new issue