forked from Kistler-Group/sdbus-cpp
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:
co-authored by
Stanislav Angelovic
parent
118faa58f6
commit
fa9569fdd9
+15
-4
@@ -98,10 +98,20 @@ namespace sdbus::internal {
|
||||
using SignalName = std::string;
|
||||
struct SignalData
|
||||
{
|
||||
signal_handler callback_;
|
||||
SlotPtr slot_;
|
||||
SignalData(Proxy& proxy, signal_handler callback, SlotPtr slot)
|
||||
: proxy(proxy)
|
||||
, callback(std::move(callback))
|
||||
, slot(std::move(slot))
|
||||
{}
|
||||
Proxy& proxy;
|
||||
signal_handler callback;
|
||||
// slot_ must be listed after callback_ to ensure that slot_ is destructed first.
|
||||
// Destructing the slot_ will sd_bus_slot_unref() the callback.
|
||||
// Only after sd_bus_slot_unref(), we can safely delete the callback. The bus mutex (SdBus::sdbusMutex_)
|
||||
// ensures that sd_bus_slot_unref() and the callback execute sequentially.
|
||||
SlotPtr slot;
|
||||
};
|
||||
std::map<SignalName, SignalData> signals_;
|
||||
std::map<SignalName, std::unique_ptr<SignalData>> signals_;
|
||||
};
|
||||
std::map<InterfaceName, InterfaceData> interfaces_;
|
||||
|
||||
@@ -150,6 +160,7 @@ namespace sdbus::internal {
|
||||
{
|
||||
std::unique_lock lock(mutex_);
|
||||
auto asyncCallSlots = std::move(calls_);
|
||||
calls_ = {};
|
||||
lock.unlock();
|
||||
|
||||
// Releasing call slot pointer acquires global sd-bus mutex. We have to perform the release
|
||||
@@ -159,8 +170,8 @@ namespace sdbus::internal {
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<void*, std::shared_ptr<CallData>> calls_;
|
||||
std::mutex mutex_;
|
||||
std::unordered_map<void*, std::shared_ptr<CallData>> calls_;
|
||||
} pendingAsyncCalls_;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user