You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(outputmonitor): don't let the smart-receiver callback outlive its owner
SetOutput() copied srCallback out from under gpioLock and invoked the copy
after releasing it. The callback is installed by FalconV5Support and captures
its raw 'this', so the copy carries no ownership: a string-config reload
destroying that object between the copy and the call left the dispatch writing
into freed memory. The destructor's unregister could not prevent it -- it can
only clear the member, never a copy already on another thread's stack. The
window is reachable because "Set Port Status" arrives on the API, MQTT, GPIO,
and scheduler threads while the reload runs elsewhere.
Invoke the callback through the member under a dedicated mutex that
setSmartReceiverEventCallback() also takes. The unregister then blocks behind
any in-flight call and no call can start after it returns, so no copy escapes.
Kept separate from gpioLock so dispatch still happens with the port state
unlocked and can't re-enter into a self-deadlock.
The state the callback publishes had the same problem one level down: the
port, receiver index, and command string were three unsynchronized fields
written from the command thread and read by the packet generator on the output
thread. As well as pairing a new port with a stale command, assigning and
comparing the std::string concurrently is a torn read of a heap pointer.
Replace them with a single lock-free atomic word, snapshotted once per pass and
cleared with a compare_exchange so a request arriving mid-pass isn't dropped.
static_asserts pin the two properties that relies on: no padding (the exchange
compares the object representation) and lock-freedom, which is what keeps the
32-bit build off a libatomic lock.
Builds clean for 32-bit and 64-bit BeagleBone platforms; the padding assert was
confirmed to fail when deliberately broken.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
0 commit comments