Skip to content
Snippets Groups Projects
Commit 20a32dcd authored by Adrien Béraud's avatar Adrien Béraud
Browse files

logger: cleanup FileLog

* move pending queue to the stack

Change-Id: Ib44578aab4b8e27fd19ff564abab8d67e9b1ad00
parent 0a7809a5
No related branches found
No related tags found
No related merge requests found
...@@ -277,18 +277,14 @@ private: ...@@ -277,18 +277,14 @@ private:
std::atomic<bool> enabled_; std::atomic<bool> enabled_;
}; };
class ConsoleLog : public jami::Logger::Handler class ConsoleLog : public Logger::Handler
{ {
public: public:
static ConsoleLog& instance() static ConsoleLog& instance()
{ {
// This is an intentional memory leak!!! // Intentional memory leak:
// // Some thread can still be logging even during static destructors.
// Some thread can still be logging after DRing::fini and even
// during the static destructors called by libstdc++. Thus, we
// allocate the logger on the heap and never free it.
static ConsoleLog* self = new ConsoleLog(); static ConsoleLog* self = new ConsoleLog();
return *self; return *self;
} }
...@@ -407,18 +403,14 @@ Logger::setConsoleLog(bool en) ...@@ -407,18 +403,14 @@ Logger::setConsoleLog(bool en)
#endif #endif
} }
class SysLog : public jami::Logger::Handler class SysLog : public Logger::Handler
{ {
public: public:
static SysLog& instance() static SysLog& instance()
{ {
// This is an intentional memory leak!!! // Intentional memory leak:
// // Some thread can still be logging even during static destructors.
// Some thread can still be logging after DRing::fini and even
// during the static destructors called by libstdc++. Thus, we
// allocate the logger on the heap and never free it.
static SysLog* self = new SysLog(); static SysLog* self = new SysLog();
return *self; return *self;
} }
...@@ -453,18 +445,14 @@ Logger::setSysLog(bool en) ...@@ -453,18 +445,14 @@ Logger::setSysLog(bool en)
SysLog::instance().enable(en); SysLog::instance().enable(en);
} }
class MonitorLog : public jami::Logger::Handler class MonitorLog : public Logger::Handler
{ {
public: public:
static MonitorLog& instance() static MonitorLog& instance()
{ {
// This is an intentional memory leak!!! // Intentional memory leak
// // Some thread can still be logging even during static destructors.
// Some thread can still be logging after DRing::fini and even
// during the static destructors called by libstdc++. Thus, we
// allocate the logger on the heap and never free it.
static MonitorLog* self = new MonitorLog(); static MonitorLog* self = new MonitorLog();
return *self; return *self;
} }
...@@ -486,18 +474,14 @@ Logger::setMonitorLog(bool en) ...@@ -486,18 +474,14 @@ Logger::setMonitorLog(bool en)
MonitorLog::instance().enable(en); MonitorLog::instance().enable(en);
} }
class FileLog : public jami::Logger::Handler class FileLog : public Logger::Handler
{ {
public: public:
static FileLog& instance() static FileLog& instance()
{ {
// This is an intentional memory leak!!! // Intentional memory leak:
// // Some thread can still be logging even during static destructors.
// Some thread can still be logging after DRing::fini and even
// during the static destructors called by libstdc++. Thus, we
// allocate the logger on the heap and never free it.
static FileLog* self = new FileLog(); static FileLog* self = new FileLog();
return *self; return *self;
} }
...@@ -508,33 +492,28 @@ public: ...@@ -508,33 +492,28 @@ public:
thread_.join(); thread_.join();
} }
if (file_.is_open()) { std::ofstream file;
file_.close();
}
if (not path.empty()) { if (not path.empty()) {
file_.open(path, std::ofstream::out | std::ofstream::app); file.open(path, std::ofstream::out | std::ofstream::app);
enable(true); enable(true);
} else { } else {
enable(false); enable(false);
return; return;
} }
thread_ = std::thread([this] { thread_ = std::thread([this, file = std::move(file)]() mutable {
std::vector<Logger::Msg> pendingQ_;
while (isEnable()) { while (isEnable()) {
{ {
std::unique_lock lk(mtx_); std::unique_lock lk(mtx_);
cv_.wait(lk, [&] { return not isEnable() or not currentQ_.empty(); }); cv_.wait(lk, [&] { return not isEnable() or not currentQ_.empty(); });
if (not isEnable())
if (not isEnable()) {
break; break;
}
std::swap(currentQ_, pendingQ_); std::swap(currentQ_, pendingQ_);
} }
do_consume(pendingQ_); do_consume(file, pendingQ_);
pendingQ_.clear(); pendingQ_.clear();
} }
}); });
...@@ -543,45 +522,38 @@ public: ...@@ -543,45 +522,38 @@ public:
~FileLog() ~FileLog()
{ {
notify([=] { enable(false); }); notify([=] { enable(false); });
if (thread_.joinable())
if (thread_.joinable()) {
thread_.join(); thread_.join();
} }
}
virtual void consume(jami::Logger::Msg& msg) override virtual void consume(Logger::Msg& msg) override
{ {
notify([&, this] { currentQ_.push_back(std::move(msg)); }); notify([&, this] { currentQ_.emplace_back(std::move(msg)); });
} }
private: private:
template<typename T> template<typename T>
void notify(T func) void notify(T func)
{ {
std::unique_lock lk(mtx_); std::lock_guard lk(mtx_);
func(); func();
cv_.notify_one(); cv_.notify_one();
} }
void do_consume(const std::vector<jami::Logger::Msg>& messages) void do_consume(std::ofstream& file, const std::vector<Logger::Msg>& messages)
{ {
for (const auto& msg : messages) { for (const auto& msg : messages) {
file_ << msg.header_ << msg.payload_.get(); file << msg.header_ << msg.payload_.get();
if (msg.linefeed_) { if (msg.linefeed_)
file_ << ENDL; file << ENDL;
}
} }
file.flush();
file_.flush();
} }
std::vector<jami::Logger::Msg> currentQ_; std::vector<Logger::Msg> currentQ_;
std::vector<jami::Logger::Msg> pendingQ_;
std::mutex mtx_; std::mutex mtx_;
std::condition_variable cv_; std::condition_variable cv_;
std::ofstream file_;
std::thread thread_; std::thread thread_;
}; };
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment