Skip to content

Commit bf02298

Browse files
committed
[logger] Make map access thread safe and proper terminate thread
1 parent a90529f commit bf02298

File tree

2 files changed

+96
-29
lines changed

2 files changed

+96
-29
lines changed

common/logger.cpp

+85-27
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414
#include "consumerstatetable.h"
1515
#include "producerstatetable.h"
1616

17-
namespace swss {
17+
using namespace swss;
1818

19-
void err_exit(const char *fn, int ln, int e, const char *fmt, ...)
19+
#define MUTEX std::lock_guard<std::mutex> _lock(getInstance().m_mutex);
20+
21+
void swss::err_exit(const char *fn, int ln, int e, const char *fmt, ...)
2022
{
2123
va_list ap;
2224
char buff[1024];
@@ -31,13 +33,34 @@ void err_exit(const char *fn, int ln, int e, const char *fmt, ...)
3133
abort();
3234
}
3335

34-
Logger::~Logger() {
35-
if (m_settingThread) {
36-
terminateSettingThread = true;
36+
Logger::~Logger()
37+
{
38+
terminateSettingThread();
39+
}
40+
41+
void Logger::terminateSettingThread()
42+
{
43+
// can't be executed under mutex, since it can cause deadlock
44+
45+
if (m_settingThread)
46+
{
47+
m_terminateSettingThread = true;
48+
3749
m_settingThread->join();
50+
51+
m_settingThread = nullptr;
52+
53+
m_terminateSettingThread = false;
3854
}
3955
}
4056

57+
void Logger::restartSettingThread()
58+
{
59+
terminateSettingThread();
60+
61+
m_settingThread.reset(new std::thread(&Logger::settingThread, this));
62+
}
63+
4164
const Logger::PriorityStringMap Logger::priorityStringMap = {
4265
{ "EMERG", SWSS_EMERG },
4366
{ "ALERT", SWSS_ALERT },
@@ -85,17 +108,27 @@ void Logger::swssOutputNotify(const std::string &component, const std::string &o
85108
}
86109
}
87110

88-
void Logger::linkToDbWithOutput(const std::string &dbName, const PriorityChangeNotify& prioNotify, const std::string& defPrio, const OutputChangeNotify& outputNotify, const std::string& defOutput)
111+
void Logger::linkToDbWithOutput(
112+
const std::string& dbName,
113+
const PriorityChangeNotify& prioNotify,
114+
const std::string& defPrio,
115+
const OutputChangeNotify& outputNotify,
116+
const std::string& defOutput)
89117
{
90118
auto& logger = getInstance();
91119

92-
// Initialize internal DB with observer
93-
logger.m_settingChangeObservers.insert(std::make_pair(dbName, std::make_pair(prioNotify, outputNotify)));
120+
std::string prio, output;
121+
122+
{
123+
MUTEX;
124+
125+
// Initialize internal DB with observer
126+
logger.m_settingChangeObservers.insert(std::make_pair(dbName, std::make_pair(prioNotify, outputNotify)));
127+
}
128+
94129
DBConnector db("LOGLEVEL_DB", 0);
95-
auto keys = db.keys("*");
96130

97131
std::string key = dbName + ":" + dbName;
98-
std::string prio, output;
99132
bool doUpdate = false;
100133
auto prioPtr = db.hget(key, DAEMON_LOGLEVEL);
101134
auto outputPtr = db.hget(key, DAEMON_LOGOUTPUT);
@@ -130,8 +163,14 @@ void Logger::linkToDbWithOutput(const std::string &dbName, const PriorityChangeN
130163
table.set(dbName, fieldValues);
131164
}
132165

133-
logger.m_currentPrios[dbName] = prio;
134-
logger.m_currentOutputs[dbName] = output;
166+
{
167+
MUTEX;
168+
logger.m_currentPrios[dbName] = prio;
169+
logger.m_currentOutputs[dbName] = output;
170+
}
171+
172+
// execute callback outside mutex
173+
135174
prioNotify(dbName, prio);
136175
outputNotify(dbName, output);
137176
}
@@ -143,10 +182,9 @@ void Logger::linkToDb(const std::string &dbName, const PriorityChangeNotify& pri
143182

144183
void Logger::linkToDbNative(const std::string &dbName, const char * defPrio)
145184
{
146-
auto& logger = getInstance();
147-
148185
linkToDb(dbName, swssPrioNotify, defPrio);
149-
logger.m_settingThread.reset(new std::thread(&Logger::settingThread, &logger));
186+
187+
getInstance().restartSettingThread();
150188
}
151189

152190
Logger &Logger::getInstance()
@@ -171,10 +209,12 @@ void Logger::settingThread()
171209
DBConnector db("LOGLEVEL_DB", 0);
172210
std::map<std::string, std::shared_ptr<ConsumerStateTable>> selectables;
173211

174-
while (!terminateSettingThread)
212+
while (!m_terminateSettingThread)
175213
{
176214
if (selectables.size() < m_settingChangeObservers.size())
177215
{
216+
MUTEX;
217+
178218
for (const auto& i : m_settingChangeObservers)
179219
{
180220
const std::string &dbName = i.first;
@@ -208,9 +248,17 @@ void Logger::settingThread()
208248
dynamic_cast<ConsumerStateTable *>(selectable)->pop(koValues);
209249
std::string key = kfvKey(koValues), op = kfvOp(koValues);
210250

211-
if ((op != SET_COMMAND) || (m_settingChangeObservers.find(key) == m_settingChangeObservers.end()))
251+
std::pair<PriorityChangeNotify, OutputChangeNotify> pair;
252+
212253
{
213-
continue;
254+
MUTEX;
255+
256+
if ((op != SET_COMMAND) || (m_settingChangeObservers.find(key) == m_settingChangeObservers.end()))
257+
{
258+
continue;
259+
}
260+
261+
pair = m_settingChangeObservers.at(key);
214262
}
215263

216264
auto values = kfvFieldsValues(koValues);
@@ -219,13 +267,21 @@ void Logger::settingThread()
219267
const std::string &field = fvField(i), &value = fvValue(i);
220268
if ((field == DAEMON_LOGLEVEL) && (value != m_currentPrios[key]))
221269
{
222-
m_currentPrios[key] = value;
223-
m_settingChangeObservers[key].first(key, value);
270+
{
271+
MUTEX;
272+
m_currentPrios[key] = value;
273+
}
274+
275+
pair.first(key, value);
224276
}
225277
else if ((field == DAEMON_LOGOUTPUT) && (value != m_currentOutputs[key]))
226278
{
227-
m_currentOutputs[key] = value;
228-
m_settingChangeObservers[key].second(key, value);
279+
{
280+
MUTEX;
281+
m_currentOutputs[key] = value;
282+
}
283+
284+
pair.second(key, value);
229285
}
230286

231287
break;
@@ -246,14 +302,16 @@ void Logger::write(Priority prio, const char *fmt, ...)
246302

247303
if (m_output == SWSS_SYSLOG)
248304
{
249-
vsyslog(prio, fmt, ap);
305+
vsyslog(prio, fmt, ap);
250306
}
251307
else
252308
{
253309
std::stringstream ss;
254310
ss << std::setw(6) << std::right << priorityToString(prio);
255311
ss << fmt << std::endl;
256-
std::lock_guard<std::mutex> lock(m_mutex);
312+
313+
MUTEX;
314+
257315
if (m_output == SWSS_STDOUT)
258316
{
259317
vprintf(ss.str().c_str(), ap);
@@ -283,7 +341,9 @@ void Logger::wthrow(Priority prio, const char *fmt, ...)
283341
std::stringstream ss;
284342
ss << std::setw(6) << std::right << priorityToString(prio);
285343
ss << fmt << std::endl;
286-
std::lock_guard<std::mutex> lock(m_mutex);
344+
345+
MUTEX;
346+
287347
if (m_output == SWSS_STDOUT)
288348
{
289349
vprintf(ss.str().c_str(), ap);
@@ -363,5 +423,3 @@ Logger::ScopeTimer::~ScopeTimer()
363423

364424
Logger::getInstance().write(swss::Logger::SWSS_NOTICE, ":- %s: %s took %lf sec", m_fun, m_msg.c_str(), duration);
365425
}
366-
367-
};

common/logger.h

+11-2
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,14 @@ class Logger
7676
static Logger &getInstance();
7777
static void setMinPrio(Priority prio);
7878
static Priority getMinPrio();
79-
static void linkToDbWithOutput(const std::string &dbName, const PriorityChangeNotify& prioNotify, const std::string& defPrio, const OutputChangeNotify& outputNotify, const std::string& defOutput);
79+
80+
static void linkToDbWithOutput(
81+
const std::string& dbName,
82+
const PriorityChangeNotify& prioNotify,
83+
const std::string& defPrio,
84+
const OutputChangeNotify& outputNotify,
85+
const std::string& defOutput);
86+
8087
static void linkToDb(const std::string &dbName, const PriorityChangeNotify& notify, const std::string& defPrio);
8188
// Must be called after all linkToDb to start select from DB
8289
static void linkToDbNative(const std::string &dbName, const char * defPrio="NOTICE");
@@ -137,6 +144,8 @@ class Logger
137144
static void swssOutputNotify(const std::string &component, const std::string &outputStr);
138145

139146
void settingThread();
147+
void terminateSettingThread();
148+
void restartSettingThread();
140149

141150
LogSettingChangeObservers m_settingChangeObservers;
142151
std::map<std::string, std::string> m_currentPrios;
@@ -145,7 +154,7 @@ class Logger
145154
std::atomic<Output> m_output = { SWSS_SYSLOG };
146155
std::unique_ptr<std::thread> m_settingThread;
147156
std::mutex m_mutex;
148-
volatile bool terminateSettingThread = false;
157+
volatile bool m_terminateSettingThread = false;
149158
};
150159

151160
}

0 commit comments

Comments
 (0)