There is a race in using singleton-static class object b/w mds thread
and application thread - caller of exit() api.
This patch still uses singleton but making the instance shared_ptr
to ensure the resource will not be destroyed if it is being used.
---
src/log/agent/lga_agent.cc | 7 ++-----
src/log/agent/lga_agent.h | 21 ++++++++++++++-------
src/log/agent/lga_api.cc | 20 ++++++++++----------
src/log/agent/lga_mds.cc | 32 ++++++++++++++++----------------
src/log/agent/lga_state.cc | 2 +-
src/log/agent/lga_util.cc | 10 +++++-----
6 files changed, 48 insertions(+), 44 deletions(-)
diff --git a/src/log/agent/lga_agent.cc b/src/log/agent/lga_agent.cc
index bf9caa935..1000bb3fd 100644
--- a/src/log/agent/lga_agent.cc
+++ b/src/log/agent/lga_agent.cc
@@ -108,7 +108,7 @@ ScopeData::~ScopeData() {
recovery2_unlock(is_locked_);
}
- LogAgent::instance().EnterCriticalSection();
+ LogAgent::instance()->EnterCriticalSection();
LogClient* client = client_data_->client;
bool* is_updated = client_data_->is_updated;
RefCounter::Degree client_degree = client_data_->value;
@@ -128,15 +128,12 @@ ScopeData::~ScopeData() {
stream->RestoreRefCounter(caller, stream_degree, *stream_is_updated);
}
}
- LogAgent::instance().LeaveCriticalSection();
+ LogAgent::instance()->LeaveCriticalSection();
}
//------------------------------------------------------------------------------
// LogAgent
//------------------------------------------------------------------------------
-// Singleton represents LOG agent.
-LogAgent LogAgent::me_;
-
LogAgent::LogAgent() {
client_list_.clear();
// There is high risk of calling one @LogClient method
diff --git a/src/log/agent/lga_agent.h b/src/log/agent/lga_agent.h
index 0049da054..0c32ea33b 100644
--- a/src/log/agent/lga_agent.h
+++ b/src/log/agent/lga_agent.h
@@ -19,12 +19,14 @@
#define SRC_LOG_AGENT_LGA_AGENT_H_
#include <atomic>
+#include <memory>
#include <string>
#include <vector>
-#include "mds/mds_papi.h"
#include <saAis.h>
-#include "base/macros.h"
#include <saLog.h>
+
+#include "base/macros.h"
+#include "mds/mds_papi.h"
#include "log/common/lgsv_msg.h"
#include "log/common/lgsv_defs.h"
#include "log/agent/lga_common.h"
@@ -80,7 +82,15 @@ class LogClient;
//<
class LogAgent {
public:
- static LogAgent& instance() { return me_; }
+ static std::shared_ptr<LogAgent>& instance() {
+ // Ensure this static singleton instance is only destroyed when
+ // no one is using it. Note that: static data can be destroyed
+ // in log application thread which calls exit() libc. So, introducing
+ // shared_ptr<> to avoid races among threads.
+ static std::shared_ptr<LogAgent> me =
+ std::shared_ptr<LogAgent>{new LogAgent()};
+ return me;
+ }
//<
// C++ APIs wrapper for corresponding C LOG Agent APIs
@@ -158,11 +168,11 @@ class LogAgent {
// Introduce these public interface for MDS thread use.
void EnterCriticalSection();
void LeaveCriticalSection();
+ ~LogAgent() {}
private:
// Not allow to create @LogAgent object, except the singleton object @me_.
LogAgent();
- ~LogAgent() {}
// True if there is no Active SC, otherwise false
bool no_active_log_server() const;
@@ -274,9 +284,6 @@ class LogAgent {
// LGS LGA sync params
NCS_SEL_OBJ lgs_sync_sel_;
- // Singleton represents LOG Agent in LOG application process
- static LogAgent me_;
-
DELETE_COPY_AND_MOVE_OPERATORS(LogAgent);
};
diff --git a/src/log/agent/lga_api.cc b/src/log/agent/lga_api.cc
index 37a1cc650..97dbf1d31 100644
--- a/src/log/agent/lga_api.cc
+++ b/src/log/agent/lga_api.cc
@@ -39,7 +39,7 @@
SaAisErrorT saLogInitialize(SaLogHandleT* logHandle,
const SaLogCallbacksT* callbacks,
SaVersionT* version) {
- return LogAgent::instance().saLogInitialize(logHandle, callbacks, version);
+ return LogAgent::instance()->saLogInitialize(logHandle, callbacks, version);
}
/***************************************************************************
@@ -69,7 +69,7 @@ SaAisErrorT saLogInitialize(SaLogHandleT* logHandle,
***************************************************************************/
SaAisErrorT saLogSelectionObjectGet(SaLogHandleT logHandle,
SaSelectionObjectT* selectionObject) {
- return LogAgent::instance().saLogSelectionObjectGet(logHandle,
+ return LogAgent::instance()->saLogSelectionObjectGet(logHandle,
selectionObject);
}
@@ -96,7 +96,7 @@ SaAisErrorT saLogSelectionObjectGet(SaLogHandleT logHandle,
***************************************************************************/
SaAisErrorT saLogDispatch(SaLogHandleT logHandle,
SaDispatchFlagsT dispatchFlags) {
- return LogAgent::instance().saLogDispatch(logHandle, dispatchFlags);
+ return LogAgent::instance()->saLogDispatch(logHandle, dispatchFlags);
}
/***************************************************************************
@@ -122,7 +122,7 @@ SaAisErrorT saLogDispatch(SaLogHandleT logHandle,
*
***************************************************************************/
SaAisErrorT saLogFinalize(SaLogHandleT logHandle) {
- return LogAgent::instance().saLogFinalize(logHandle);
+ return LogAgent::instance()->saLogFinalize(logHandle);
}
/**
@@ -142,7 +142,7 @@ SaAisErrorT saLogStreamOpen_2(
const SaLogFileCreateAttributesT_2* logFileCreateAttributes,
SaLogStreamOpenFlagsT logStreamOpenFlags, SaTimeT timeOut,
SaLogStreamHandleT* logStreamHandle) {
- return LogAgent::instance().saLogStreamOpen_2(
+ return LogAgent::instance()->saLogStreamOpen_2(
logHandle, logStreamName, logFileCreateAttributes, logStreamOpenFlags,
timeOut, logStreamHandle);
}
@@ -161,7 +161,7 @@ SaAisErrorT saLogStreamOpenAsync_2(
SaLogHandleT logHandle, const SaNameT* logStreamName,
const SaLogFileCreateAttributesT_2* logFileCreateAttributes,
SaLogStreamOpenFlagsT logstreamOpenFlags, SaInvocationT invocation) {
- return LogAgent::instance().saLogStreamOpenAsync_2(
+ return LogAgent::instance()->saLogStreamOpenAsync_2(
logHandle, logStreamName, logFileCreateAttributes, logstreamOpenFlags,
invocation);
}
@@ -176,7 +176,7 @@ SaAisErrorT saLogStreamOpenAsync_2(
*/
SaAisErrorT saLogWriteLog(SaLogStreamHandleT logStreamHandle, SaTimeT timeOut,
const SaLogRecordT* logRecord) {
- return LogAgent::instance().saLogWriteLog(logStreamHandle, timeOut,
+ return LogAgent::instance()->saLogWriteLog(logStreamHandle, timeOut,
logRecord);
}
@@ -193,7 +193,7 @@ SaAisErrorT saLogWriteLogAsync(SaLogStreamHandleT
logStreamHandle,
SaInvocationT invocation,
SaLogAckFlagsT ackFlags,
const SaLogRecordT* logRecord) {
- return LogAgent::instance().saLogWriteLogAsync(logStreamHandle, invocation,
+ return LogAgent::instance()->saLogWriteLogAsync(logStreamHandle, invocation,
ackFlags, logRecord);
}
/**
@@ -204,7 +204,7 @@ SaAisErrorT saLogWriteLogAsync(SaLogStreamHandleT
logStreamHandle,
* @return SaAisErrorT
*/
SaAisErrorT saLogStreamClose(SaLogStreamHandleT logStreamHandle) {
- return LogAgent::instance().saLogStreamClose(logStreamHandle);
+ return LogAgent::instance()->saLogStreamClose(logStreamHandle);
}
/**
@@ -217,5 +217,5 @@ SaAisErrorT saLogStreamClose(SaLogStreamHandleT
logStreamHandle) {
*/
SaAisErrorT saLogLimitGet(SaLogHandleT logHandle, SaLogLimitIdT limitId,
SaLimitValueT* limitValue) {
- return LogAgent::instance().saLogLimitGet(logHandle, limitId, limitValue);
+ return LogAgent::instance()->saLogLimitGet(logHandle, limitId, limitValue);
}
diff --git a/src/log/agent/lga_mds.cc b/src/log/agent/lga_mds.cc
index ca949577f..07db48d2c 100644
--- a/src/log/agent/lga_mds.cc
+++ b/src/log/agent/lga_mds.cc
@@ -516,9 +516,9 @@ static uint32_t lga_lgs_msg_proc(lgsv_msg_t *lgsv_msg,
// Lookup the hdl rec by client_id
LogClient *client = nullptr;
uint32_t id = lgsv_msg->info.cbk_info.lgs_client_id;
- LogAgent::instance().EnterCriticalSection();
- if (nullptr == (client = LogAgent::instance().SearchClientById(id))) {
- LogAgent::instance().LeaveCriticalSection();
+ LogAgent::instance()->EnterCriticalSection();
+ if (nullptr == (client = LogAgent::instance()->SearchClientById(id))) {
+ LogAgent::instance()->LeaveCriticalSection();
TRACE("regid not found");
lga_msg_destroy(lgsv_msg);
return NCSCC_RC_FAILURE;
@@ -527,12 +527,12 @@ static uint32_t lga_lgs_msg_proc(lgsv_msg_t *lgsv_msg,
// @client is being deleted in other thread. DO NOT touch this.
bool updated = false;
if (client->FetchAndIncreaseRefCounter(__func__, &updated) == -1) {
- LogAgent::instance().LeaveCriticalSection();
+ LogAgent::instance()->LeaveCriticalSection();
lga_msg_destroy(lgsv_msg);
TRACE_LEAVE();
return rc;
}
- LogAgent::instance().LeaveCriticalSection();
+ LogAgent::instance()->LeaveCriticalSection();
switch (lgsv_msg->type) {
case LGSV_LGS_CBK_MSG:
@@ -554,7 +554,7 @@ static uint32_t lga_lgs_msg_proc(lgsv_msg_t *lgsv_msg,
TRACE_2("LGSV_CLM_NODE_STATUS_CALLBACK clm_node_status: %d", status);
std::atomic<SaClmClusterChangesT> &clm_node_state =
- LogAgent::instance().atomic_get_clm_node_state();
+ LogAgent::instance()->atomic_get_clm_node_state();
clm_node_state =
lgsv_msg->info.cbk_info.clm_node_status_cbk.clm_node_status;
// A client becomes stale if Node loses CLM Membership.
@@ -644,7 +644,7 @@ static uint32_t lga_mds_svc_evt(struct ncsmds_callback_info
*mds_cb_info) {
TRACE("%s\t NCSMDS_NO_ACTIVE", __func__);
// This is a temporary server down e.g. during switch/fail over
if (mds_cb_info->info.svc_evt.i_svc_id == NCSMDS_SVC_ID_LGS) {
- LogAgent::instance().NoActiveLogServer();
+ LogAgent::instance()->NoActiveLogServer();
}
break;
@@ -658,7 +658,7 @@ static uint32_t lga_mds_svc_evt(struct ncsmds_callback_info
*mds_cb_info) {
// Notify to LOG Agent that no LOG server exist.
// In turn, it will inform to all its log clients
// and all log streams belong to each log client.
- LogAgent::instance().NoLogServer();
+ LogAgent::instance()->NoLogServer();
// Stop the recovery thread if it is running
lga_no_server_state_set();
}
@@ -671,11 +671,11 @@ static uint32_t lga_mds_svc_evt(struct
ncsmds_callback_info *mds_cb_info) {
TRACE("%s\t NCSMDS_UP", __func__);
// Inform to LOG agent that LOG server is up from headless
// and provide it the LOG server destination address too.
- LogAgent::instance().HasActiveLogServer(
+ LogAgent::instance()->HasActiveLogServer(
mds_cb_info->info.svc_evt.i_dest);
- if (LogAgent::instance().waiting_log_server_up() == true) {
+ if (LogAgent::instance()->waiting_log_server_up() == true) {
// Signal waiting thread
- m_NCS_SEL_OBJ_IND(LogAgent::instance().get_lgs_sync_sel());
+ m_NCS_SEL_OBJ_IND(LogAgent::instance()->get_lgs_sync_sel());
}
// Start recovery
lga_serv_recov1state_set();
@@ -1236,7 +1236,7 @@ uint32_t lga_mds_init() {
NCSMDS_INFO mds_info;
uint32_t rc = NCSCC_RC_SUCCESS;
MDS_SVC_ID svc = NCSMDS_SVC_ID_LGS;
- std::atomic<MDS_HDL> &mds_hdl = LogAgent::instance().atomic_get_mds_hdl();
+ std::atomic<MDS_HDL> &mds_hdl = LogAgent::instance()->atomic_get_mds_hdl();
TRACE_ENTER();
// Create the ADEST for LGA and get the pwe hdl
@@ -1307,9 +1307,9 @@ uint32_t lga_mds_msg_sync_send(lgsv_msg_t *i_msg,
lgsv_msg_t **o_msg,
SaTimeT timeout, uint32_t prio) {
NCSMDS_INFO mds_info;
uint32_t rc = NCSCC_RC_SUCCESS;
- std::atomic<MDS_HDL> &mds_hdl = LogAgent::instance().atomic_get_mds_hdl();
+ std::atomic<MDS_HDL> &mds_hdl = LogAgent::instance()->atomic_get_mds_hdl();
std::atomic<MDS_DEST> &lgs_mds_dest =
- LogAgent::instance().atomic_get_lgs_mds_dest();
+ LogAgent::instance()->atomic_get_lgs_mds_dest();
TRACE_ENTER();
@@ -1358,9 +1358,9 @@ uint32_t lga_mds_msg_sync_send(lgsv_msg_t *i_msg,
lgsv_msg_t **o_msg,
******************************************************************************/
uint32_t lga_mds_msg_async_send(lgsv_msg_t *i_msg, uint32_t prio) {
NCSMDS_INFO mds_info;
- std::atomic<MDS_HDL> &mds_hdl = LogAgent::instance().atomic_get_mds_hdl();
+ std::atomic<MDS_HDL> &mds_hdl = LogAgent::instance()->atomic_get_mds_hdl();
std::atomic<MDS_DEST> &lgs_mds_dest =
- LogAgent::instance().atomic_get_lgs_mds_dest();
+ LogAgent::instance()->atomic_get_lgs_mds_dest();
TRACE_ENTER();
osafassert(i_msg != nullptr);
diff --git a/src/log/agent/lga_state.cc b/src/log/agent/lga_state.cc
index 05c7a85ee..970fe27d2 100644
--- a/src/log/agent/lga_state.cc
+++ b/src/log/agent/lga_state.cc
@@ -97,7 +97,7 @@ static void *recovery2_thread(void *dummy) {
// Recover all log clients. During this time, any call of LOG APIs
// return TRY_AGAIN until the recovery is done.
- LogAgent::instance().RecoverAllLogClients();
+ LogAgent::instance()->RecoverAllLogClients();
// All clients are recovered (or removed). Or recovery is aborted
// Change to not recovering state RecoveryState::kNormal
diff --git a/src/log/agent/lga_util.cc b/src/log/agent/lga_util.cc
index f4d0f970a..0bb91aaee 100644
--- a/src/log/agent/lga_util.cc
+++ b/src/log/agent/lga_util.cc
@@ -40,17 +40,17 @@ static unsigned int lga_create() {
unsigned int rc = NCSCC_RC_SUCCESS;
// Create and init sel obj for mds sync
- NCS_SEL_OBJ* lgs_sync_sel = LogAgent::instance().get_lgs_sync_sel();
+ NCS_SEL_OBJ* lgs_sync_sel = LogAgent::instance()->get_lgs_sync_sel();
m_NCS_SEL_OBJ_CREATE(lgs_sync_sel);
std::atomic<bool>& lgs_sync_wait =
- LogAgent::instance().atomic_get_lgs_sync_wait();
+ LogAgent::instance()->atomic_get_lgs_sync_wait();
lgs_sync_wait = true;
// register with MDS
if ((NCSCC_RC_SUCCESS != (rc = lga_mds_init()))) {
rc = NCSCC_RC_FAILURE;
// Delete the lga init instances
- LogAgent::instance().RemoveAllLogClients();
+ LogAgent::instance()->RemoveAllLogClients();
return rc;
}
@@ -64,7 +64,7 @@ static unsigned int lga_create() {
lgs_sync_wait = false;
std::atomic<SaClmClusterChangesT>& clm_state =
- LogAgent::instance().atomic_get_clm_node_state();
+ LogAgent::instance()->atomic_get_clm_node_state();
clm_state = SA_CLM_NODE_JOINED;
// No longer needed
@@ -82,7 +82,7 @@ static unsigned int lga_create() {
unsigned int lga_startup() {
unsigned int rc = NCSCC_RC_SUCCESS;
ScopeLock lock(init_lock);
- std::atomic<MDS_HDL>& mds_hdl = LogAgent::instance().atomic_get_mds_hdl();
+ std::atomic<MDS_HDL>& mds_hdl = LogAgent::instance()->atomic_get_mds_hdl();
TRACE_ENTER();
--
2.19.2
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel