diff options
| author | Shulhan <ms@kilabit.info> | 2026-02-15 12:44:24 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2026-02-15 12:45:13 +0700 |
| commit | 1844b9e48d0f5f7f3e9c8de026181d04d74c92ab (patch) | |
| tree | 967889384daa96e58fdefd6315e134ab8029a2e7 /lib | |
| parent | ccc9926635c1702337ac6fd1038bd7b903afa7f9 (diff) | |
| download | pakakeh.go-1844b9e48d0f5f7f3e9c8de026181d04d74c92ab.tar.xz | |
lib/http: fix possible data race in SSE connection
When server's handler call Write or WriteRaw, there is possibility that
the worker for keeping the connection alive also call Write at the same
time, which cause the data race.
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/http/sse_conn.go | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/lib/http/sse_conn.go b/lib/http/sse_conn.go index 055a5793..8d2f0b76 100644 --- a/lib/http/sse_conn.go +++ b/lib/http/sse_conn.go @@ -10,6 +10,7 @@ import ( "net" "net/http" "strings" + "sync" "time" ) @@ -28,6 +29,10 @@ type SSEConn struct { bufrw *bufio.ReadWriter conn net.Conn + + // bufrwMtx protects the concurrent write between client and + // workerKeepAlive. + bufrwMtx sync.Mutex } // WriteEvent write message with optional event type and id to client. @@ -61,21 +66,23 @@ func (ep *SSEConn) WriteEvent(event, data string, id *string) (err error) { ep.writeData(&buf, data, id) - _, err = ep.bufrw.Write(buf.Bytes()) + err = ep.WriteRaw(buf.Bytes()) if err != nil { return fmt.Errorf(`WriteEvent: %w`, err) } - ep.bufrw.Flush() return nil } // WriteRaw write raw event message directly, without any parsing. func (ep *SSEConn) WriteRaw(msg []byte) (err error) { + ep.bufrwMtx.Lock() _, err = ep.bufrw.Write(msg) if err != nil { + ep.bufrwMtx.Unlock() return fmt.Errorf(`WriteRaw: %w`, err) } ep.bufrw.Flush() + ep.bufrwMtx.Unlock() return nil } |
