Having troubles with Mutex

I am coding an api where I have few goroutines to do stuff. So two of the goroutines are responsible to send msgs to clients over a websocket connection. But due to some strange bug which I am not able to figure out, every msgs are being sent twice to clients. so, I figured to post here to get help to understand what could be going wrong. Below are the code snippets of relevant code. You can see whole code on github.

helpers package:

// BroadcastBoardUpdates broadcasts board updates to users
func BroadcastBoardUpdates(i *models.Instance) {
	for {
		if i.GetBroadcastBoardFlag() {
			for x := range i.AllPlayers {
				msg := models.NewStateMsg{constants.StateUpBcastMsg, i.AllPlayers[i.CurrentTurn].UserName, i.Board}
				err := i.AllPlayers[x].WriteToWebsocket(msg)
				if err != nil {
					log.Printf("error: %v", err)
					i.AllPlayers[x].CleanupWs()
				}
			}
			i.SetBroadcastBoardFlag(false)
		}
		if i.IsOver {
			return
		}
	}
}

// BroadcastWinner broadcasts winner to users
func BroadcastWinner(i *models.Instance) {
	for {
		if i.IsOver {
			return
		}
		if i.GetIfSomeoneWon() {
			for x := range i.AllPlayers {
				msg := models.WinnerMsg{constants.UserWonMsg, i.Winner.UserName, i.Winner.Color}
				err := i.AllPlayers[x].WriteToWebsocket(msg)
				if err != nil {
					log.Printf("error: %v", err)
					i.AllPlayers[x].CleanupWs()
				}
			}
			i.IsOver = true
		}
	}
}

instance package

// SetBroadcastBoardFlag sets broadcast board state flag safely
func (i *Instance) SetBroadcastBoardFlag(val bool) {
	i.bbcastMutex.Lock()
	i.broadcastBoardFlag = val
	i.bbcastMutex.Unlock()
}

// GetBroadcastBoardFlag sets broadcast board state flag safely
func (i *Instance) GetBroadcastBoardFlag() bool {
	i.bbcastMutex.Lock()
	defer i.bbcastMutex.Unlock()
	return i.broadcastBoardFlag
}

// GetIfSomeoneWon returns if someone won
func (i *Instance) GetIfSomeoneWon() bool {
	i.allPlayedMutex.Lock()
	val := i.didWin
	i.allPlayedMutex.Unlock()
	return val
}

// SetIfSomeoneWon sets didWin
func (i *Instance) SetIfSomeoneWon(val bool) {
	i.allPlayedMutex.Lock()
	i.didWin = val
	i.allPlayedMutex.Unlock()
}

simulate package

// ChainReaction is called after each move and spreads the orbs on the board
func ChainReaction(gameInstance *models.Instance, move models.MoveMsg) error {

	helpers.SetIfAllPlayedOnce(gameInstance, player.UserName)

	gameInstance.SetBroadcastBoardFlag(true)

	if won {
		gameInstance.SetWinner(player)
	}

	return nil
}

Did you run with -race parameter? It may help debugging the problem. Can you provide minimal runnable code?

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.