Websocket: Im getting error: "concurrent write to websocket connection"

Created on 19 Mar 2016  路  11Comments  路  Source: gorilla/websocket

Im getting error: "concurrent write to websocket connection" when i try made a simple game server.

My server is here:
https://github.com/Shoen/phaser_multiplayer_demo/blob/master/server.go

After a lot of movement from the same player, if crashes in this line:

if err = p.Socket.WriteJSON(player.position(false)); err != nil {

Can anyone help me?

Most helpful comment

Connections do not support concurrent writers. Protect write with a mutex:

type Player struct {
    Y      int             // Y position of the player
    X      int             // X position
    Id     string          // a unique id to identify the player by the frontend
    Socket *websocket.Conn // websocket connection of the player
    mu      sync.Mutex
}

func (p *Player) send(v interface{}) error {
    p.mu.Lock()
    defer p.mu.Unlock()
    return p.Socket.WriteJSON(v)
}

Replace all other p.Socket.WriteJSON(v) with calls with p.send(v).

I suggest running the application with the race detector. I suspect that there are other races.

All 11 comments

Connections do not support concurrent writers. Protect write with a mutex:

type Player struct {
    Y      int             // Y position of the player
    X      int             // X position
    Id     string          // a unique id to identify the player by the frontend
    Socket *websocket.Conn // websocket connection of the player
    mu      sync.Mutex
}

func (p *Player) send(v interface{}) error {
    p.mu.Lock()
    defer p.mu.Unlock()
    return p.Socket.WriteJSON(v)
}

Replace all other p.Socket.WriteJSON(v) with calls with p.send(v).

I suggest running the application with the race detector. I suspect that there are other races.

Problem solved. There is any gorilla native way to do it? My code is the correct way?

There is any gorilla native way to do it?

I don't understand what you are asking. Can you please try to rephrase the question or add detail?

Ok.

I think that it is a common problem, concurrency. My question is about a gorilla implementation method that already have this mutex control, or everybody need do the same thing?

The server code that i show is the best method to make the server or have any best practices?

The application is responsible for ensuring that there's a single writer. A mutex is one way to do this. See the chat example for another approach.

See the Gorilla websocket examples for examples of how to write a server.

The code that you showed has a data race on Players and on the websocket connections.

type redisReceiver struct {
    pool    *redis.Pool
    mu      sync.Mutex
    conns   map[string]*websocket.Conn
}

func (rr *redisReceiver) broadcast(data []byte) {
    rr.mu.Lock()
    defer rr.mu.Unlock()
    for id, conn := range rr.conns {
        if err := conn.WriteMessage(websocket.TextMessage, data); err != nil {
            fmt.Println("Error writting data to connection! Closing and removing Connection")
            rr.deRegister(id)
        }
    }
}

This is my code. I am getting "concurrent write to websocket connection" in this part some times
What am I wrong?

@TianDaGe Is there code not shown here that writes to a connection?

nothing, that is all to write data via websocket connection. I am using Redis for broadcast.

I am using this sample
https://github.com/heroku-examples/go-websocket-chat-demo

My code is in the redis.go

@garyburd, I am waiting you :)

I do not have time to debug the application. Ask the author for help or search the application for all calls to WriteMessage and ensure that each call is protected by the mutex.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

melnikalex picture melnikalex  路  7Comments

markusthoemmes picture markusthoemmes  路  7Comments

guybrand picture guybrand  路  19Comments

joshdvir picture joshdvir  路  50Comments

IngCr3at1on picture IngCr3at1on  路  6Comments