Skip to content

[BUG] Broadcast deadlocks when concurrency #59

Open
@AlanTianx

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:

  1. When nsConn is disconnected, it will cause Server.Broadcast() internal blocking'' when broadcasting a message on the websocket.OnNamespaceDisconnect or websocket.OnRoomLeft event
  2. 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")
}

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions