Problem
OpcuaPlugin::pending_reports_ (std::vector<std::function<void()>>) had no synchronization but was accessed from two threads:
- poll thread:
publish_values -> flush_pending_reports, and on_alarm_change/on_event_alarm -> send_or_buffer
- REST thread: FaultProvider
clear_fault -> send_clear_fault -> send_or_buffer
A reallocating push_back while the other thread iterated the vector is a use-after-free -> heap corruption -> SIGSEGV inside libros2_medkit_opcua_plugin.so. The header comment even wrongly asserted "poll-thread only, no lock".
Repro
Reproduced deterministically (SEGFAULT, core dumped) with concurrent REST clear_fault against the poll thread.
Fix
Guard the buffer with a mutex and swap-and-dispatch outside the lock, so ROS I/O never runs while holding it. Added a regression test that crashes without the fix.
Fixed in #519
Problem
OpcuaPlugin::pending_reports_(std::vector<std::function<void()>>) had no synchronization but was accessed from two threads:publish_values->flush_pending_reports, andon_alarm_change/on_event_alarm->send_or_bufferclear_fault->send_clear_fault->send_or_bufferA reallocating
push_backwhile the other thread iterated the vector is a use-after-free -> heap corruption -> SIGSEGV insidelibros2_medkit_opcua_plugin.so. The header comment even wrongly asserted "poll-thread only, no lock".Repro
Reproduced deterministically (SEGFAULT, core dumped) with concurrent REST
clear_faultagainst the poll thread.Fix
Guard the buffer with a mutex and swap-and-dispatch outside the lock, so ROS I/O never runs while holding it. Added a regression test that crashes without the fix.
Fixed in #519