最近在某大型视觉导航程序工程里集成了强大的Easylogging++日志模块,用得很爽。直到一连串死机BUG的出现......
1 问题
正常情况下我们使用Easylogging++不会出现什么问题,我也是这样认为的,并且坚信。当你在多线程里这样疯狂输出日志时:
#include <chrono>
#include <thread>
#include "easylogging++.h"
INITIALIZE_EASYLOGGINGPP
void fun0()
{
while (1)
{
LOG(INFO) << "this is sub thread: " << std::this_thread::get_id();
std::chrono::milliseconds dura(10);
std::this_thread::sleep_for(dura);
}
}
void fun1()
{
while (1)
{
LOG(INFO) << "this is sub thread: " << std::this_thread::get_id();
std::chrono::milliseconds dura(10);
std::this_thread::sleep_for(dura);
}
}
void fun2()
{
while (1)
{
LOG(INFO) << "this is sub thread: " << std::this_thread::get_id();
std::chrono::milliseconds dura(10);
std::this_thread::sleep_for(dura);
}
}
void fun3()
{
while (1)
{
LOG(INFO) << "this is sub thread: " << std::this_thread::get_id();
std::chrono::milliseconds dura(10);
std::this_thread::sleep_for(dura);
}
}
void fun4()
{
while (1)
{
LOG(INFO) << "this is sub thread: " << std::this_thread::get_id();
std::chrono::milliseconds dura(10);
std::this_thread::sleep_for(dura);
}
}
void fun5()
{
while (1)
{
LOG(INFO) << "this is sub thread: " << std::this_thread::get_id();
std::chrono::milliseconds dura(10);
std::this_thread::sleep_for(dura);
}
}
void fun6()
{
while (1)
{
LOG(INFO) << "this is sub thread: " << std::this_thread::get_id();
std::chrono::milliseconds dura(10);
std::this_thread::sleep_for(dura);
}
}
void fun7()
{
while (1)
{
LOG(INFO) << "this is sub thread: " << std::this_thread::get_id();
std::chrono::milliseconds dura(10);
std::this_thread::sleep_for(dura);
}
}
void fun8()
{
while (1)
{
LOG(INFO) << "this is sub thread: " << std::this_thread::get_id();
std::chrono::milliseconds dura(10);
std::this_thread::sleep_for(dura);
}
}
void fun9()
{
while (1)
{
LOG(INFO) << "this is sub thread: " << std::this_thread::get_id();
std::chrono::milliseconds dura(10);
std::this_thread::sleep_for(dura);
}
}
void fun10()
{
while (1)
{
LOG(INFO) << "this is sub thread: " << std::this_thread::get_id();
std::chrono::milliseconds dura(10);
std::this_thread::sleep_for(dura);
}
}
int main(int argc, char **argv)
{
/// 使用默认配置
el::Configurations defaultConf;
defaultConf.setToDefault();
defaultConf.setGlobally(el::ConfigurationType::Enabled, "true");
defaultConf.setGlobally(el::ConfigurationType::ToFile, "true");
defaultConf.setGlobally(el::ConfigurationType::ToStandardOutput, "false");
defaultConf.setGlobally(el::ConfigurationType::Format, "[%datetime{%H:%m:%s:%g}] [%level] %msg");
defaultConf.setGlobally(el::ConfigurationType::Filename, "vslam.log");
defaultConf.setGlobally(el::ConfigurationType::MillisecondsWidth, "3");
defaultConf.setGlobally(el::ConfigurationType::PerformanceTracking, "false");
defaultConf.setGlobally(el::ConfigurationType::MaxLogFileSize, "104857600"); // 100MB
defaultConf.setGlobally(el::ConfigurationType::LogFlushThreshold, "0");
defaultConf.set(el::Level::Trace, el::ConfigurationType::Enabled, "true");
defaultConf.set(el::Level::Info, el::ConfigurationType::Enabled, "true");
defaultConf.set(el::Level::Debug, el::ConfigurationType::Enabled, "true");
defaultConf.set(el::Level::Error, el::ConfigurationType::Enabled, "true");
defaultConf.set(el::Level::Warning, el::ConfigurationType::Enabled, "true");
el::Loggers::reconfigureAllLoggers(defaultConf);
LOG(INFO) << argv[0] << " start !!!!";
LOG(INFO) << "start vslam !!!!";
std::thread t0(fun0);
std::thread t1(fun1);
std::thread t2(fun2);
std::thread t3(fun3);
std::thread t4(fun4);
std::thread t5(fun5);
std::thread t6(fun6);
std::thread t7(fun7);
std::thread t8(fun8);
std::thread t9(fun9);
std::thread t10(fun10);
while(1)
{
LOG(INFO) << "this is main thread: " << std::this_thread::get_id();
std::chrono::milliseconds dura(1);
std::this_thread::sleep_for(dura);
}
LOG(INFO) << "bye! bye! vslam will exit.";
return 0;
}
出现了致命BUG
2 尝试解决
将
inline bool isFlushNeeded(Level level) {
return ++m_unflushedCount.find(level)->second >= m_typedConfigurations->logFlushThreshold(level);
}
修改成
inline bool isFlushNeeded(Level level) {
if (!m_unflushedCount.empty())
{
auto it = m_unflushedCount.find(level);
if (it != m_unflushedCount.end())
{
return ++it->second >= m_typedConfigurations->logFlushThreshold(level);
}
}
return false;
}
以为解决了,可是过了半小时后