Open
Description
Describe the bug
I found in the actual application that the Broadcast() method will cause a deadlock
To Reproduce
Steps to reproduce the behavior:
- When
nsConn
is disconnected, it will causeServer.Broadcast()
internal blocking'' when broadcasting a message on thewebsocket.OnNamespaceDisconnect
orwebsocket.OnRoomLeft
event - code
package main
import (
"fmt"
gorilla "github.com/gorilla/websocket"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/websocket"
"github.com/kataras/neffos"
"net/http"
"time"
)
func main() {
namespace, room, event := "test", "ttt", "ch"
chatServer := websocket.New(
websocket.GorillaUpgrader(gorilla.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
// todo 允许所有的CORS 跨域请求,正式环境可以关闭
CheckOrigin: func(r *http.Request) bool {
return true
},
}),
websocket.WithTimeout{
WriteTimeout: time.Second * 60,
ReadTimeout: time.Second * 60,
Namespaces: websocket.Namespaces{
namespace: websocket.Events{
websocket.OnNamespaceConnected: func(nsConn *websocket.NSConn, msg websocket.Message) error {
fmt.Println("OnNamespaceConnected", nsConn.Conn.ID())
nsConn.JoinRoom(nil, room)
return nil
},
websocket.OnNamespaceDisconnect: func(nsConn *websocket.NSConn, msg websocket.Message) error {
fmt.Println("OnNamespaceDisconnect", nsConn.Conn.ID())
// Todo The broadcast here will cause blocking in `server.start()`
//nsConn.Conn.Server().Broadcast(nsConn, neffos.Message{
// Body: []byte("我离开了room" + nsConn.Conn.ID()),
// Namespace: namespace,
// Room: room,
// To: "",
// Event: event,
//})
// Todo Add a certain delay and everything is normal
time.AfterFunc(time.Millisecond*50, func() {
nsConn.Conn.Server().Broadcast(nsConn, neffos.Message{
Body: []byte("我离开了room" + nsConn.Conn.ID()),
Namespace: namespace,
Room: room,
To: "",
Event: event,
})
})
return nil
},
websocket.OnRoomJoined: func(nsConn *websocket.NSConn, msg websocket.Message) error {
fmt.Println("OnRoomJoined", nsConn.Conn.ID())
nsConn.Emit(event, []byte("我是单独消息"))
nsConn.Conn.Server().Broadcast(nil, neffos.Message{
Body: []byte("我加入了room" + nsConn.Conn.ID()),
Namespace: namespace,
Room: room,
To: "",
Event: event,
})
return nil
},
websocket.OnRoomLeft: func(nsConn *websocket.NSConn, msg websocket.Message) error {
fmt.Println("OnRoomLeft", nsConn.Conn.ID(), nsConn.Conn.IsClosed())
// Todo The broadcast here will cause blocking in `server.start()`
//nsConn.Conn.Server().Broadcast(nsConn, neffos.Message{
// Body: []byte("我离开了room" + nsConn.Conn.ID()),
// Namespace: namespace,
// Room: room,
// To: "",
// Event: event,
//})
// Todo Add a certain delay and everything is normal
time.AfterFunc(time.Millisecond*50, func() {
nsConn.Conn.Server().Broadcast(nsConn, neffos.Message{
Body: []byte("我离开了room" + nsConn.Conn.ID()),
Namespace: namespace,
Room: room,
To: "",
Event: event,
})
})
return nil
},
},
},
},
)
app := iris.New()
app.Get("/e", websocket.Handler(chatServer, func(ctx iris.Context) string {
return ctx.URLParam("id")
}))
// Todo If you don't want to lose messages, please turn it on
chatServer.SyncBroadcaster = true
app.Listen("0.0.0.0:8090")
}