fix: resolve concurrent write crash on gorilla/websocket by adding wsWriteMu mutex
All checks were successful
Deploy on Master Change / deploy (push) Successful in 42s

This commit is contained in:
2026-07-01 13:42:13 +07:00
parent 604ce9ea16
commit a3b986674e
3 changed files with 36 additions and 40 deletions

BIN
client/.DS_Store vendored

Binary file not shown.

View File

@@ -140,6 +140,7 @@ type App struct {
chatUnread int
replyStaffID uint
fetchAppsMu sync.Mutex
wsWriteMu sync.Mutex
}
type LocalStats struct {
@@ -608,23 +609,32 @@ func (a *App) GetStats() map[string]any {
}
}
// safeWriteWS writes a message to the WebSocket connection thread-safely
func (a *App) safeWriteWS(msg any) error {
a.mu.Lock()
conn := a.wsConn
a.mu.Unlock()
if conn == nil {
return errors.New("websocket connection is nil")
}
a.wsWriteMu.Lock()
defer a.wsWriteMu.Unlock()
return conn.WriteJSON(msg)
}
// SendWebcamFrame truyền webcam frame từ JS frontend lên máy chủ qua WS
func (a *App) SendWebcamFrame(frameBase64 string) {
if !a.isMonitoringActive() {
return
}
a.mu.Lock()
conn := a.wsConn
a.mu.Unlock()
if conn != nil {
_ = conn.WriteJSON(map[string]any{
"event": "webcam_stream_frame",
"data": map[string]any{
"imageBuffer": frameBase64,
},
})
}
_ = a.safeWriteWS(map[string]any{
"event": "webcam_stream_frame",
"data": map[string]any{
"imageBuffer": frameBase64,
},
})
}
// authStorageScanner chỉ quét localStorage khi người dùng chủ động mở trang đăng nhập
@@ -1225,18 +1235,12 @@ func (a *App) startScreenshotStream() {
continue
}
a.mu.Lock()
conn := a.wsConn
a.mu.Unlock()
if conn != nil {
_ = conn.WriteJSON(map[string]any{
"event": "screenshot_stream_frame",
"data": map[string]any{
"imageBuffer": frame,
},
})
}
_ = a.safeWriteWS(map[string]any{
"event": "screenshot_stream_frame",
"data": map[string]any{
"imageBuffer": frame,
},
})
case <-a.streamScStop:
return
}
@@ -1301,22 +1305,14 @@ func (a *App) startWebcamStream() {
emptyCount = 0
sentCount++
a.mu.Lock()
conn := a.wsConn
a.mu.Unlock()
if conn != nil {
err := conn.WriteJSON(map[string]any{
"event": "webcam_stream_frame",
"data": map[string]any{
"imageBuffer": frame,
},
})
if sentCount <= 5 {
log.Printf("[WS] Webcam frame #%d sent (len=%d, err=%v)", sentCount, len(frame), err)
}
} else if sentCount <= 5 {
log.Printf("[WS] Webcam frame #%d: no WS connection", sentCount)
err := a.safeWriteWS(map[string]any{
"event": "webcam_stream_frame",
"data": map[string]any{
"imageBuffer": frame,
},
})
if sentCount <= 5 {
log.Printf("[WS] Webcam frame #%d sent (len=%d, err=%v)", sentCount, len(frame), err)
}
case <-a.streamCamStop:
return

BIN
client/build/.DS_Store vendored

Binary file not shown.