fix(backend): fix crash when trying to update player data concurrently

This commit is contained in:
2025-03-11 12:32:36 +01:00
parent d4f194b146
commit a4a26f04d4
4 changed files with 31 additions and 0 deletions

View File

@ -93,6 +93,9 @@ func onPlayerJoin(client *socket.Socket, room *types.Room, player *types.Player)
}) })
client.On("UpdatePlayer", func(datas ...any) { client.On("UpdatePlayer", func(datas ...any) {
player.Mutex.Lock()
defer player.Mutex.Unlock()
updatePlayerRequest := types.C2S_UpdatePlayer{} updatePlayerRequest := types.C2S_UpdatePlayer{}
unpackData(datas, &updatePlayerRequest) unpackData(datas, &updatePlayerRequest)
if updatePlayerRequest.PlayerId != player.PlayerId && !player.HasPermissionBit(types.PermissionHost) { if updatePlayerRequest.PlayerId != player.PlayerId && !player.HasPermissionBit(types.PermissionHost) {
@ -114,6 +117,10 @@ func onPlayerJoin(client *socket.Socket, room *types.Room, player *types.Player)
} }
slog.Debug("Updating player data", "roomId", room.RoomId, "playerId", updatePlayerRequest.PlayerId, "username", targetPlayer.Username, "request", updatePlayerRequest) slog.Debug("Updating player data", "roomId", room.RoomId, "playerId", updatePlayerRequest.PlayerId, "username", targetPlayer.Username, "request", updatePlayerRequest)
if player != targetPlayer {
targetPlayer.Mutex.Lock()
defer targetPlayer.Mutex.Unlock()
}
if updatePlayerRequest.Username != nil { if updatePlayerRequest.Username != nil {
if room.IsUsernameAvailable(*updatePlayerRequest.Username) { if room.IsUsernameAvailable(*updatePlayerRequest.Username) {
targetPlayer.Username = *updatePlayerRequest.Username targetPlayer.Username = *updatePlayerRequest.Username
@ -133,6 +140,9 @@ func onPlayerJoin(client *socket.Socket, room *types.Room, player *types.Player)
}) })
client.On("KickPlayer", func(datas ...any) { client.On("KickPlayer", func(datas ...any) {
player.Mutex.Lock()
defer player.Mutex.Unlock()
kickPlayerRequest := types.C2S_KickPlayer{} kickPlayerRequest := types.C2S_KickPlayer{}
unpackData(datas, &kickPlayerRequest) unpackData(datas, &kickPlayerRequest)
if !player.HasPermissionBit(types.PermissionHost) { if !player.HasPermissionBit(types.PermissionHost) {
@ -153,6 +163,9 @@ func onPlayerJoin(client *socket.Socket, room *types.Room, player *types.Player)
return return
} }
if player == targetPlayer {
player.Mutex.Unlock()
}
if room.RemovePlayer(*targetPlayer) { if room.RemovePlayer(*targetPlayer) {
slog.Debug("Player was kicked from room", "playerId", player.PlayerId, "targetPlayerId", kickPlayerRequest.PlayerId, "roomId", room.RoomId) slog.Debug("Player was kicked from room", "playerId", player.PlayerId, "targetPlayerId", kickPlayerRequest.PlayerId, "roomId", room.RoomId)
if targetPlayer.Connection.IsConnected && targetPlayer.Connection.Socket != nil { if targetPlayer.Connection.IsConnected && targetPlayer.Connection.Socket != nil {
@ -163,6 +176,9 @@ func onPlayerJoin(client *socket.Socket, room *types.Room, player *types.Player)
}) })
} }
} }
if player == targetPlayer {
player.Mutex.Lock()
}
game.OnRoomUpdate(room) game.OnRoomUpdate(room)
}) })
@ -187,6 +203,9 @@ func onPlayerJoin(client *socket.Socket, room *types.Room, player *types.Player)
}) })
client.On("DrawCard", func(datas ...any) { client.On("DrawCard", func(datas ...any) {
player.Mutex.Lock()
defer player.Mutex.Unlock()
if !verifyPlayerIsActivePlayer(room, player) { if !verifyPlayerIsActivePlayer(room, player) {
return return
} }
@ -199,6 +218,9 @@ func onPlayerJoin(client *socket.Socket, room *types.Room, player *types.Player)
}) })
client.On("PlayCard", func(datas ...any) { client.On("PlayCard", func(datas ...any) {
player.Mutex.Lock()
defer player.Mutex.Unlock()
if !verifyPlayerIsActivePlayer(room, player) { if !verifyPlayerIsActivePlayer(room, player) {
return return
} }
@ -240,6 +262,9 @@ func onPlayerJoin(client *socket.Socket, room *types.Room, player *types.Player)
}) })
client.On("UpdatePlayedCard", func(datas ...any) { client.On("UpdatePlayedCard", func(datas ...any) {
player.Mutex.Lock()
defer player.Mutex.Unlock()
if !verifyPlayerIsActivePlayer(room, player) { if !verifyPlayerIsActivePlayer(room, player) {
return return
} }

View File

@ -28,6 +28,7 @@ func (serializable *SerializablePlayer) ToPlayer(cardDeckId int) types.Player {
Permissions: serializable.Permissions, Permissions: serializable.Permissions,
Connection: types.WebsocketConnection{IsConnected: false}, Connection: types.WebsocketConnection{IsConnected: false},
Cards: cards, Cards: cards,
Mutex: &sync.Mutex{},
} }
player.ResetInactivity() player.ResetInactivity()
return player return player

View File

@ -87,6 +87,7 @@ func JoinRoom(room *types.Room, requestedUsername string) *types.Player {
Connection: types.WebsocketConnection{ Connection: types.WebsocketConnection{
IsConnected: false, IsConnected: false,
}, },
Mutex: &sync.Mutex{},
} }
player.ResetInactivity() player.ResetInactivity()
room.AppendPlayer(player) room.AppendPlayer(player)

View File

@ -35,6 +35,7 @@ type Player struct {
Cards []Card `json:"-"` Cards []Card `json:"-"`
Connection WebsocketConnection `bson:"-" json:"-"` Connection WebsocketConnection `bson:"-" json:"-"`
InactivityTimeout int `bson:"-" json:"-"` InactivityTimeout int `bson:"-" json:"-"`
Mutex *sync.Mutex
} }
func (player *Player) ResetInactivity() { func (player *Player) ResetInactivity() {
@ -93,6 +94,9 @@ func (room *Room) AppendPlayer(player *Player) {
func (room *Room) RemovePlayer(target Player) bool { func (room *Room) RemovePlayer(target Player) bool {
room.PlayersMutex.Lock() room.PlayersMutex.Lock()
defer room.PlayersMutex.Unlock() defer room.PlayersMutex.Unlock()
target.Mutex.Lock()
defer target.Mutex.Unlock()
return room.RemovePlayerUnsafe(target) return room.RemovePlayerUnsafe(target)
} }