Handling websocket writeerror

I save my websockets in map using a uuid e.g.

sockets["123456"] = *websocket.Conn

and a function that passes a message to a channel

func (mr MessageRequest) Send(msg []byte) {
	mr.mu.RLock()
	defer mr.mu.RUnlock()
	for _, socket := range mr.sockets {
		mr.chat.broadcast <- Message{
			socket:  socket,
			message: msg,
			chat:    mr.chat,
		}
	}
}

The channel that processes the message is as follows

case mr := <-c.broadcast:
			msg := mr.message

			if c.sockets[mr.socket] != nil {
				if err := c.sockets[mr.socket].WriteMessage(websocket.TextMessage, msg); err != nil {
					c.sockets[mr.socket].SetWriteDeadline(time.Now().Add(10 * time.Second))
					c.sockets[mr.socket].WriteMessage(websocket.CloseMessage, []byte{})
					c.sockets[mr.socket].Close()
					go c.Unregister(c.sockets[mr.socket])
				}
			}

The problem comes from this line when there are many clients connected, and some clients disconnects quickly.

if err := c.sockets[mr.socket].WriteMessage(websocket.TextMessage, msg); err != nil 

The error is

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x10 pc=0x139b430]
goroutine 138 [running]:
github.com/fasthttp/websocket.(*Conn).WriteMessage(0x164f3c0?, 0xc0002a57d0?, {0xc0000380e0, 0x70, 0x70})
/Users/username/go/pkg/mod/github.com/fasthttp/websocket@v1.5.0/conn.go:760 +0x30

I think it happens because sockets[“123456”] has been deleted when it Unregister. I already did a check using if c.sockets[mr.socket] != nil { but my application still crash because of the line above.

I don’t know how to solve this scenario and I need help please.

PS: If it helps, my unregister function is like the following

		case connection := <-c.unregister:
			uuid := connection.uuid
			if c.sockets[uuid] != nil { // avoid multiple deletion
				c.mu.Lock()
				delete(c.sockets, uuid)
				c.mu.Unlock()
			}
		

To check if an item has been deleted from a map, do this

if c, ok := sockets["123456"]; ok {
    //Still there

Thank you. I have changed to your codes, however I am still getting the error when I have many connections/disconnections concurrently.

I tried to print the uuid from the socket before writing the on the socket but there’s no problem accessing the slice.

I have added a Rlock like coded below as well, but it’s still happening. Theorically speaking it should not have a nil pointer dereference error right?

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x10 pc=0x139b430]

	        c.mu.RLock()
			// if c.sockets[mr.socket] != nil {
			if socket, ok := c.sockets[mr.socket]; ok {
                pp.Print(socket.Locals("uuid")) //<--- this prints (accessible)
				if err := socket.WriteMessage(websocket.TextMessage, msg); err != nil { //<-- this is error
					socket.SetWriteDeadline(time.Now().Add(10 * time.Second))
					socket.WriteMessage(websocket.CloseMessage, []byte{})
					socket.Close()
					go c.Unregister(socket)
				}
			}
			c.mu.RUnlock()

Error also points to this line in fasthttp websocket/conn.go at c98746c10029a4885af35f497980303ea218f409 · fasthttp/websocket · GitHub

please show the map definition…

This is my struct

type Chat struct {
	register   chan Connection
	broadcast  chan Message
	unregister chan Connection
	join       chan RoomRequest
	leave      chan RoomRequest
	rooms      map[string][]string
	sockets    map[string]*websocket.Conn. //<-- This is the one causing memory issues
	mu         *sync.RWMutex
	stats      *Stats
}

Thank u in advanced.

I think you would need to check the state of the socket before send a message

> if socket != nil && !socket.IsCloseError && !socket.IsUnexpectedCloseError {   
>    if err := socket.WriteMessage(websocket.TextMessage, msg); err != nil {
>       ....
>    }
> }

@Yamil_Bracho Thank you for your time.

After meddling for so long, turn out it’s a bug from fasthttp websocket throwing unnecessary panic when it should have returned an error. It has been fixed here → Description: by gokpm · Pull Request #31 · fasthttp/websocket · GitHub

Oops!!! Thanks it’s good to know that…