mirror of
https://github.com/Telecominfraproject/oopt-tai-implementations.git
synced 2025-10-30 01:32:42 +00:00
mux: fix race condition of notification oid conversion
Signed-off-by: Wataru Ishida <ishida@nel-america.com>
This commit is contained in:
committed by
Wataru Ishida
parent
db57d98ff5
commit
318f221930
@@ -247,7 +247,6 @@ void Multiplexier::notify(notification_context* ctx, tai_object_id_t real_oid, t
|
|||||||
if ( oid == TAI_NULL_OBJECT_ID ) {
|
if ( oid == TAI_NULL_OBJECT_ID ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto key = std::pair<tai_object_id_t, tai_attr_id_t>(oid, ctx->notify_id);
|
|
||||||
tai_attribute_t dst;
|
tai_attribute_t dst;
|
||||||
tai_alloc_info_t info;
|
tai_alloc_info_t info;
|
||||||
info.reference = src;
|
info.reference = src;
|
||||||
@@ -272,7 +271,10 @@ void Multiplexier::notify(notification_context* ctx, tai_object_id_t real_oid, t
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->handler.notify(ctx->handler.context, oid, &dst);
|
{
|
||||||
|
std::unique_lock<std::mutex> lk(ctx->mutex);
|
||||||
|
ctx->handler.notify(ctx->handler.context, oid, &dst);
|
||||||
|
}
|
||||||
err:
|
err:
|
||||||
tai_metadata_free_attr_value(meta, &dst, nullptr);
|
tai_metadata_free_attr_value(meta, &dst, nullptr);
|
||||||
}
|
}
|
||||||
@@ -292,6 +294,7 @@ tai_status_t Multiplexier::set_attributes( std::function<tai_status_t(ModuleAdap
|
|||||||
std::vector<tai_attribute_t> attrs;
|
std::vector<tai_attribute_t> attrs;
|
||||||
tai_alloc_info_t info;
|
tai_alloc_info_t info;
|
||||||
auto t = object_type_query(oid);
|
auto t = object_type_query(oid);
|
||||||
|
std::vector<notification_key> n_to_clear;
|
||||||
for ( auto i = 0; i < attr_count; i++ ) {
|
for ( auto i = 0; i < attr_count; i++ ) {
|
||||||
auto meta = tai_metadata_get_attr_metadata(t, attr_list[i].id);
|
auto meta = tai_metadata_get_attr_metadata(t, attr_list[i].id);
|
||||||
if ( meta == nullptr ) {
|
if ( meta == nullptr ) {
|
||||||
@@ -312,8 +315,19 @@ tai_status_t Multiplexier::set_attributes( std::function<tai_status_t(ModuleAdap
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
attrs.emplace_back(attr);
|
attrs.emplace_back(attr);
|
||||||
|
// we can't delete m_notification_map[key] before calling f() since
|
||||||
|
// the adapter can still call the notification callback.
|
||||||
|
// store the keys to be removed into n_to_clear and delete them after calling f()
|
||||||
|
if ( meta->attrvaluetype == TAI_ATTR_VALUE_TYPE_NOTIFICATION && attr.value.notification.notify == nullptr ) {
|
||||||
|
n_to_clear.emplace_back(notification_key(oid, attr.id));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ret = f(m_adapter, id, attrs.size(), attrs.data());
|
ret = f(m_adapter, id, attrs.size(), attrs.data());
|
||||||
|
|
||||||
|
for ( auto& key : n_to_clear ) {
|
||||||
|
delete m_notification_map[key];
|
||||||
|
m_notification_map.erase(key);
|
||||||
|
}
|
||||||
err:
|
err:
|
||||||
if ( free_attributes(t, attrs) < 0 ) {
|
if ( free_attributes(t, attrs) < 0 ) {
|
||||||
return TAI_STATUS_FAILURE;
|
return TAI_STATUS_FAILURE;
|
||||||
@@ -365,7 +379,7 @@ tai_status_t Multiplexier::convert_oid(tai_object_id_t oid, const tai_attribute_
|
|||||||
}
|
}
|
||||||
return oid;
|
return oid;
|
||||||
};
|
};
|
||||||
auto key = std::pair<tai_object_id_t, tai_attr_id_t>(oid, src->id);
|
auto key = notification_key(oid, src->id);
|
||||||
|
|
||||||
switch (meta->attrvaluetype) {
|
switch (meta->attrvaluetype) {
|
||||||
case TAI_ATTR_VALUE_TYPE_OID:
|
case TAI_ATTR_VALUE_TYPE_OID:
|
||||||
@@ -405,14 +419,12 @@ tai_status_t Multiplexier::convert_oid(tai_object_id_t oid, const tai_attribute_
|
|||||||
dst->value.notification.notify = n->handler.notify;
|
dst->value.notification.notify = n->handler.notify;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ( src->value.notification.notify == nullptr ) {
|
if ( src->value.notification.notify != nullptr ) {
|
||||||
delete m_notification_map[key];
|
|
||||||
m_notification_map.erase(key);
|
|
||||||
} else {
|
|
||||||
if ( m_notification_map.find(key) == m_notification_map.end() ) {
|
if ( m_notification_map.find(key) == m_notification_map.end() ) {
|
||||||
m_notification_map[key] = new notification_context();
|
m_notification_map[key] = new notification_context();
|
||||||
}
|
}
|
||||||
auto n = m_notification_map[key];
|
auto n = m_notification_map[key];
|
||||||
|
std::unique_lock<std::mutex> lk(n->mutex);
|
||||||
n->mux = this;
|
n->mux = this;
|
||||||
n->adapter = adapter;
|
n->adapter = adapter;
|
||||||
n->handler = src->value.notification;
|
n->handler = src->value.notification;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "tai.h"
|
#include "tai.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
class OIDAllocator {
|
class OIDAllocator {
|
||||||
public:
|
public:
|
||||||
@@ -36,8 +37,11 @@ struct notification_context {
|
|||||||
ModuleAdapter* adapter;
|
ModuleAdapter* adapter;
|
||||||
tai_notification_handler_t handler;
|
tai_notification_handler_t handler;
|
||||||
tai_attr_id_t notify_id;
|
tai_attr_id_t notify_id;
|
||||||
|
std::mutex mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using notification_key = std::pair<tai_object_id_t, tai_attr_id_t>;
|
||||||
|
|
||||||
// singleton
|
// singleton
|
||||||
class Multiplexier {
|
class Multiplexier {
|
||||||
public:
|
public:
|
||||||
@@ -57,6 +61,9 @@ class Multiplexier {
|
|||||||
if ( m_pa != nullptr ) {
|
if ( m_pa != nullptr ) {
|
||||||
delete m_pa;
|
delete m_pa;
|
||||||
}
|
}
|
||||||
|
for ( auto& n : m_notification_map ) {
|
||||||
|
delete n.second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleAdapter * get_module_adapter(const std::string& location) {
|
ModuleAdapter * get_module_adapter(const std::string& location) {
|
||||||
@@ -133,7 +140,7 @@ class Multiplexier {
|
|||||||
void operator = (const Multiplexier&){}
|
void operator = (const Multiplexier&){}
|
||||||
PlatformAdapter *m_pa;
|
PlatformAdapter *m_pa;
|
||||||
std::map<tai_object_id_t, std::pair<tai_object_id_t, ModuleAdapter* >> m_map;
|
std::map<tai_object_id_t, std::pair<tai_object_id_t, ModuleAdapter* >> m_map;
|
||||||
std::map<std::pair<tai_object_id_t, tai_attr_id_t>, notification_context*> m_notification_map;
|
std::map<notification_key, notification_context*> m_notification_map;
|
||||||
|
|
||||||
OIDAllocator m_oid_allocator;
|
OIDAllocator m_oid_allocator;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user