ASAN violation when deleting EventQueue
The following test
SCENARIO("Event subscriptions with interface change event (event queue)")
{
int idlver = GENERATE(TangoTest::idlversion(Tango::MIN_IDL_DEV_INTR));
GIVEN("a device proxy to a simple IDLv" << idlver << " device")
{
TangoTest::Context ctx{"esm", "EventSubModeDevice", idlver};
std::shared_ptr<Tango::DeviceProxy> device = ctx.get_proxy();
WHEN("we subscribe to the interface change event")
{
using namespace Catch::Matchers;
using namespace TangoTest::Matchers;
const int event_queue_size{10};
TangoTest::Subscription sub{device, Tango::INTERFACE_CHANGE_EVENT, event_queue_size};
THEN("we got an interface change event")
{
Tango::DevIntrChangeEventDataList list;
device->get_events(sub.get_id(), list);
REQUIRE_THAT(list, !IsEmpty());
auto event{list[0]};
REQUIRE_THAT(event->errors, IsEmpty());
// FIXME hangs when accessing event->dev_started,
REQUIRE_THAT(event, EventDeviceStarted(false));
REQUIRE_THAT(event, EventType(Tango::INTERFACE_CHANGE_EVENT));
// REQUIRE_THAT(event, EventCommandNamesMatches(UnorderedRangeEquals(static_commands)));
// REQUIRE_THAT(event, EventAttributeNamesMatches(UnorderedRangeEquals(static_attributes)));
// REQUIRE_THAT(event, EventReason(Tango::EventReason::Update));
}
}
}
}
with $cmake --build build/debug-asan && gdb -ex run --args ./build/debug-asan/tests/Catch2Tests "Scenario: Event subscriptions with interface change event (event queue)"
provokes
Thread 1 "Catch2Tests" received signal SIGSEGV, Segmentation fault.
0x00007ffff741ceda in Tango::EventQueue::~EventQueue (this=<optimized out>) at /home/thomas/devel/cppTango/src/client/eventqueue.cpp:136
136 delete ready_event_buffer[i];
(gdb) bt
#0 0x00007ffff741ceda in Tango::EventQueue::~EventQueue (this=<optimized out>) at /home/thomas/devel/cppTango/src/client/eventqueue.cpp:136
#1 0x00007ffff73cad52 in Tango::EventConsumer::unsubscribe_event (this=<optimized out>, event_id=<optimized out>)
at /home/thomas/devel/cppTango/src/client/event.cpp:1918
#2 0x00007ffff716fcee in Tango::DeviceProxy::unsubscribe_event (this=<optimized out>, event_id=2)
at /home/thomas/devel/cppTango/src/client/devapi_base.cpp:8565
#3 0x0000555555e684bd in TangoTest::Subscription<Tango::DeviceProxy>::~Subscription (this=0x7fffffffcca0)
at /home/thomas/devel/cppTango/tests/catch2/utils/utils.h:362
#4 CATCH2_INTERNAL_TEST_42 () at /home/thomas/devel/cppTango/tests/catch2_event_subscription_mode.cpp:454
#5 0x00005555561a0ae2 in Catch::(anonymous namespace)::TestInvokerAsFunction::invoke() const ()
#6 0x000055555618bd0b in Catch::TestCaseHandle::invoke() const ()
#7 0x000055555618ac77 in Catch::RunContext::invokeActiveTestCase() ()
#8 0x000055555618a9d4 in Catch::RunContext::runCurrentTest() ()
#9 0x0000555556188de4 in Catch::RunContext::runTest(Catch::TestCaseHandle const&) ()
#10 0x000055555613b61a in Catch::(anonymous namespace)::TestGroup::execute() ()
#11 0x000055555613c966 in Catch::Session::runInternal() ()
#12 0x000055555613c4fa in Catch::Session::run() ()
#13 0x0000555556100c89 in Catch::Session::run<char> (this=0x7bfff20e0420, argc=2, argv=0x7fffffffd948)
at /usr/local/include/catch2/catch_session.hpp:41
#14 TangoTest::test_main (argc=<optimized out>, argv=<optimized out>) at /home/thomas/devel/cppTango/tests/catch2/utils/entry_points.cpp:31
#15 0x0000555556101930 in main (argc=<optimized out>, argv=0x7fffffffd948) at /home/thomas/devel/cppTango/tests/catch2/utils/entry_points.cpp:163
The problem is that EventQueue:~EventQueue accesses the ready event buffer but we don't have elements in that vector. The fix is easy, just iterate only over the elements of each vector. We also need to delete and clear dev_inter_event_buffer in the dtor.
Edited by Thomas Braun