Issue 133 race in proxy destruct (#177)

* fix construct/destruct order of mutex/data in AsnycCalls

Destroying a mutex which might still be owned leads to undefined behaviour.
It wasn't the case here but using the right order is more resistant to future bugs.

* proxy AsnycCalls: don't leave map in unspecified state

* fix 133: use thread-safe container for proxy interfaces list

* proxy callback payload uses concrete signalData

* proxy: revert adding the wrapper class InterfaceContainer

It's no longer required and simplifies the locking logic.

* Proxy: avoid additional lambda wrapper around signal callbacks

As proposed in
https://github.com/Kistler-Group/sdbus-cpp/pull/177#issuecomment-834439707
option 3.

Still TODO: Avoid relying on std::map's non-invalidatable by adding just
std::unique_ptr<Proxy::InterfaceData::SignalData> to the container.

* proxy: add missing underscore prefix

* proxy: put InterfaceData::SignalData into a unique_ptr

This ways, we avoid relying on std::map's non-invalidatable references.

* proxy: code style: get raw pointer directly

* style: fix code style

Co-authored-by: Stanislav Angelovic <stanislav.angelovic@siemens.com>
This commit is contained in:
Urs Ritzmann
2021-06-03 18:53:38 +02:00
committed by GitHub
co-authored by Stanislav Angelovic
parent 118faa58f6
commit fa9569fdd9
2 changed files with 29 additions and 23 deletions
+14 -19
View File
@@ -34,7 +34,7 @@
#include <systemd/sd-bus.h>
#include <cassert>
#include <chrono>
#include <thread>
#include <utility>
namespace sdbus::internal {
@@ -160,7 +160,7 @@ void Proxy::registerSignalHandler( const std::string& interfaceName
auto& interface = interfaces_[interfaceName];
InterfaceData::SignalData signalData{std::move(signalHandler), nullptr};
auto signalData = std::make_unique<InterfaceData::SignalData>(*this, std::move(signalHandler), nullptr);
auto insertionResult = interface.signals_.emplace(signalName, std::move(signalData));
auto inserted = insertionResult.second;
@@ -182,13 +182,13 @@ void Proxy::registerSignalHandlers(sdbus::internal::IConnection& connection)
for (auto& signalItem : signalsOnInterface)
{
const auto& signalName = signalItem.first;
auto& slot = signalItem.second.slot_;
slot = connection.registerSignalHandler( destination_
, objectPath_
, interfaceName
, signalName
, &Proxy::sdbus_signal_handler
, this );
auto* signalData = signalItem.second.get();
signalData->slot = connection.registerSignalHandler( destination_
, objectPath_
, interfaceName
, signalName
, &Proxy::sdbus_signal_handler
, signalData);
}
}
}
@@ -245,17 +245,12 @@ int Proxy::sdbus_async_reply_handler(sd_bus_message *sdbusMessage, void *userDat
int Proxy::sdbus_signal_handler(sd_bus_message *sdbusMessage, void *userData, sd_bus_error */*retError*/)
{
auto* proxy = static_cast<Proxy*>(userData);
assert(proxy != nullptr);
auto message = Message::Factory::create<Signal>(sdbusMessage, &proxy->connection_->getSdBusInterface());
// Note: The lookup can be optimized by using sorted vectors instead of associative containers
auto& callback = proxy->interfaces_[message.getInterfaceName()].signals_[message.getMemberName()].callback_;
assert(callback);
callback(message);
auto* signalData = static_cast<InterfaceData::SignalData*>(userData);
assert(signalData != nullptr);
assert(signalData->callback);
auto message = Message::Factory::create<Signal>(sdbusMessage, &signalData->proxy.connection_->getSdBusInterface());
signalData->callback(message);
return 0;
}