Commit 1a783c1
fix(shm): serialise concurrent writers with seq# + POSIX semaphore (fixes #195)
Two writers calling write_SM() on the same shmget() key used to
interleave strncpy() byte writes with no mutex, no semaphore, no
memory barrier, and no version counter - producing torn payloads
on the reader side.
Layout (any reader that does not know about the header will see a
leading integer and fail loudly, which is the desired signal):
bytes [0..7] uint64 little-endian sequence number
(odd = write in progress, even = ready, 0 = none)
bytes [8..end] null-terminated payload
Protocol: a seqlock under a POSIX semaphore keyed by (shm_key + 1).
The writer acquires the lock, bumps seq# to odd, memcpy's the payload,
NUL-terminates, __ATOMIC_RELEASE fence, then bumps seq# back to even.
The reader does a seqlock-style read: load seq#1, copy payload,
__ATOMIC_ACQUIRE fence, load seq#2 - accept only if seq#1 == seq#2
and seq#1 is even. Readers do not take the semaphore, so fan-out
stays cheap.
Mirrors the same change in concoredocker.hpp. Adds:
tests/test_shm_concurrency.py Python regression (fork-based, Linux)
tests/test_shm_cpp_harness.cpp fork-based C++ harness for CI
tests/test_shm_cpp_smoke.cpp header self-contained check
plus a cpp-shm-test job in .github/workflows/ci.yml that builds and
runs the harness on ubuntu-latest.1 parent a30127e commit 1a783c1
6 files changed
Lines changed: 765 additions & 80 deletions
File tree
- .github/workflows
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
96 | 96 | | |
97 | 97 | | |
98 | 98 | | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
0 commit comments