add write lock to websocket client (matches server-side Conn.lock)
client.writeFrame() is called concurrently from:
- pingLoop task (subscriber keepalive)
- readLoop auto-pong (server ping response)
- close path (connection teardown)
without serialization, concurrent writes interleave frame headers/payloads,
corrupting the stream and causing GPF in memcpy → Writer.zig → writeAll.
adds _write_lock: Io.Mutex to Client struct, acquired around the two
writeAll calls in writeFrame(). header construction and payload masking
happen outside the lock to minimize hold time.
the server-side Conn already has this pattern (lock: Io.Mutex around
writeFrame/writeFramed/writeAllIOVec). this brings the client to parity.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>