14
14
#include " consumerstatetable.h"
15
15
#include " producerstatetable.h"
16
16
17
- namespace swss {
17
+ using namespace swss ;
18
18
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, ...)
20
22
{
21
23
va_list ap;
22
24
char buff[1024 ];
@@ -31,13 +33,34 @@ void err_exit(const char *fn, int ln, int e, const char *fmt, ...)
31
33
abort ();
32
34
}
33
35
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
+
37
49
m_settingThread->join ();
50
+
51
+ m_settingThread = nullptr ;
52
+
53
+ m_terminateSettingThread = false ;
38
54
}
39
55
}
40
56
57
+ void Logger::restartSettingThread ()
58
+ {
59
+ terminateSettingThread ();
60
+
61
+ m_settingThread.reset (new std::thread (&Logger::settingThread, this ));
62
+ }
63
+
41
64
const Logger::PriorityStringMap Logger::priorityStringMap = {
42
65
{ " EMERG" , SWSS_EMERG },
43
66
{ " ALERT" , SWSS_ALERT },
@@ -85,17 +108,27 @@ void Logger::swssOutputNotify(const std::string &component, const std::string &o
85
108
}
86
109
}
87
110
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)
89
117
{
90
118
auto & logger = getInstance ();
91
119
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
+
94
129
DBConnector db (" LOGLEVEL_DB" , 0 );
95
- auto keys = db.keys (" *" );
96
130
97
131
std::string key = dbName + " :" + dbName;
98
- std::string prio, output;
99
132
bool doUpdate = false ;
100
133
auto prioPtr = db.hget (key, DAEMON_LOGLEVEL);
101
134
auto outputPtr = db.hget (key, DAEMON_LOGOUTPUT);
@@ -130,8 +163,14 @@ void Logger::linkToDbWithOutput(const std::string &dbName, const PriorityChangeN
130
163
table.set (dbName, fieldValues);
131
164
}
132
165
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
+
135
174
prioNotify (dbName, prio);
136
175
outputNotify (dbName, output);
137
176
}
@@ -143,10 +182,9 @@ void Logger::linkToDb(const std::string &dbName, const PriorityChangeNotify& pri
143
182
144
183
void Logger::linkToDbNative (const std::string &dbName, const char * defPrio)
145
184
{
146
- auto & logger = getInstance ();
147
-
148
185
linkToDb (dbName, swssPrioNotify, defPrio);
149
- logger.m_settingThread .reset (new std::thread (&Logger::settingThread, &logger));
186
+
187
+ getInstance ().restartSettingThread ();
150
188
}
151
189
152
190
Logger &Logger::getInstance ()
@@ -171,10 +209,12 @@ void Logger::settingThread()
171
209
DBConnector db (" LOGLEVEL_DB" , 0 );
172
210
std::map<std::string, std::shared_ptr<ConsumerStateTable>> selectables;
173
211
174
- while (!terminateSettingThread )
212
+ while (!m_terminateSettingThread )
175
213
{
176
214
if (selectables.size () < m_settingChangeObservers.size ())
177
215
{
216
+ MUTEX;
217
+
178
218
for (const auto & i : m_settingChangeObservers)
179
219
{
180
220
const std::string &dbName = i.first ;
@@ -208,9 +248,17 @@ void Logger::settingThread()
208
248
dynamic_cast <ConsumerStateTable *>(selectable)->pop (koValues);
209
249
std::string key = kfvKey (koValues), op = kfvOp (koValues);
210
250
211
- if ((op != SET_COMMAND) || (m_settingChangeObservers.find (key) == m_settingChangeObservers.end ()))
251
+ std::pair<PriorityChangeNotify, OutputChangeNotify> pair;
252
+
212
253
{
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);
214
262
}
215
263
216
264
auto values = kfvFieldsValues (koValues);
@@ -219,13 +267,21 @@ void Logger::settingThread()
219
267
const std::string &field = fvField (i), &value = fvValue (i);
220
268
if ((field == DAEMON_LOGLEVEL) && (value != m_currentPrios[key]))
221
269
{
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);
224
276
}
225
277
else if ((field == DAEMON_LOGOUTPUT) && (value != m_currentOutputs[key]))
226
278
{
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);
229
285
}
230
286
231
287
break ;
@@ -246,14 +302,16 @@ void Logger::write(Priority prio, const char *fmt, ...)
246
302
247
303
if (m_output == SWSS_SYSLOG)
248
304
{
249
- vsyslog (prio, fmt, ap);
305
+ vsyslog (prio, fmt, ap);
250
306
}
251
307
else
252
308
{
253
309
std::stringstream ss;
254
310
ss << std::setw (6 ) << std::right << priorityToString (prio);
255
311
ss << fmt << std::endl;
256
- std::lock_guard<std::mutex> lock (m_mutex);
312
+
313
+ MUTEX;
314
+
257
315
if (m_output == SWSS_STDOUT)
258
316
{
259
317
vprintf (ss.str ().c_str (), ap);
@@ -283,7 +341,9 @@ void Logger::wthrow(Priority prio, const char *fmt, ...)
283
341
std::stringstream ss;
284
342
ss << std::setw (6 ) << std::right << priorityToString (prio);
285
343
ss << fmt << std::endl;
286
- std::lock_guard<std::mutex> lock (m_mutex);
344
+
345
+ MUTEX;
346
+
287
347
if (m_output == SWSS_STDOUT)
288
348
{
289
349
vprintf (ss.str ().c_str (), ap);
@@ -363,5 +423,3 @@ Logger::ScopeTimer::~ScopeTimer()
363
423
364
424
Logger::getInstance ().write (swss::Logger::SWSS_NOTICE, " :- %s: %s took %lf sec" , m_fun, m_msg.c_str (), duration);
365
425
}
366
-
367
- };
0 commit comments