Closed kuchaguangjie closed 1 year ago
Also asked on stackoverflow: https://stackoverflow.com/questions/74076674/fasthttp-websocket-panic-nil-websocket-conn-beginmessage
A separate goroutine that handle close msg (part of content_ctl.go
):
// handle close - from a channel,
// TODO: use goroutine pool ?
go func() {
if r := recover(); r != nil { // TODO: is this proper ?,
fmt.Printf("recover from panic: %v\n", r)
}
closeMsg := <-(*client).CloseChan // handle close,
log.Infof("close msg received: %v", closeMsg)
// send close msg,
closeResp := &model.WsResp{
Status: closeMsg.HttpCode,
Source: model.RespSourceConn,
Msg: closeMsg.Msg,
}
log.Infof("is conn nil: %v, msg: %v\n", client.WsConn == nil, closeResp)
err = client.WriteMsg(closeResp)
if err != nil {
log.Errorf("error - on write close msg: %v", closeResp)
}
ctl.cwm.CloseAndCleanup(client.Id) // close & clean up,
}()
WsClient
struct, and its method WriteMsg()
(part of ws_model.go
): // websocket client,
type WsClient struct {
WsUser
ContentUuid string `json:"contentUuid"` // content uuid id,
WsConn *websocket.Conn `json:"-"` // websocket connection,
CloseChan chan *CloseMsg `json:"-"` // close channel,
WriteLock *sync.Mutex // write lock, to avoid concurrent write to ws connection, which will cause panic, acquire lock when write or close,
}
// write ws msg, with lock,
func (wsc *WsClient) WriteMsg(msg *WsResp) error {
if wsc.WsConn == nil {
return errutil.ErrNoConn
}
wsc.WriteLock.Lock()
err := wsc.WsConn.WriteJSON(msg)
wsc.WriteLock.Unlock()
return err
}
CloseMsg
struct (part of ws_model.go
):
// close msg sent to close chan,
type CloseMsg struct {
HttpCode int `json:"httpCode"`
Msg string `json:"msg"`
}
Problem status:
httpCode
in the CloseMsg
, if it's 418
, then I won't send the close msg.Some background:
CloseMsg
's HttpCode
.
418
is the default one, it happens only when unexpected io issue happen on the connection (e.g heroku terminate the connection due to idle ?).418
.418
might not be the best http code to use, (it's from a joke), but that doesn't effect the problem I guess.WsClient
's WriteMsg()
method, I've always checked whether the conn nil, before send msg.2022-10-16T05:19:03.088622+00:00 heroku[router]: at=error code=H15 desc="Idle connection" method=GET path="/api/v1/content/ws/RgPx8znal7AJb
2022-10-16T05:19:03.065493+00:00 app[web.1]: time="2022-10-16T05:19:03Z" level=info msg="error - on read: websocket: close 1006 (abnormal closure): unexpected EOF"
2022-10-16T05:20:57.758379+00:00 app[web.1]: time="2022-10-16T05:20:57Z" level=info msg="cleanup client, id = 'wscid-ee670cc5-4100-49d6-9857-8284d93a6d33'"
2022-10-16T05:20:57.758505+00:00 app[web.1]: time="2022-10-16T05:20:57Z" level=info msg="close msg received: &{418 close}"
Seems heroku will kill the websocket connection if there is no msg for a while. That's when 418
appear.
I've asked a question about heroku killing the websocket connection on SO: https://stackoverflow.com/questions/74084808/heroku-kill-idle-connection-websocket
Hi @kuchaguangjie,
Sorry for my delayed answer.
Fixed the panic in v1.5.1-rc.8 by @gokpm. Now returns an error instead of panic.
Thanks for your issue!
Using Fiber v2.38.1, which in turn use fasthttp/websocket v1.5.0.
App crashed with following error:
It crashed at
conn.go:479
, in functionbeginMessage()
:I've checked that
c
is not nil (as shown in log), so how it crashed ...BTW, it's deployed on heroku, I saw following log on heroku:
Not sure is it relevent.