spdlog
spdlog copied to clipboard
rotating_logger_mt crashed
When I tried to create a scroll log using the rotating_logger_mt method, the log crashed while scrolling. The crash was caused by spdlog/details/ file_help-inl.h :124, SPDLOG_INLINE void file_helper::write(const memory_buf_t &buf) { size_t msg_size = buf.size(); auto data = buf.data(); if (std::fwrite(data, 1, msg_size, fd_) ! = msg_size) { throw_spdlog_ex("Failed writing to file " + os::filename_to_str(filename_), errno); } } fd_ is empty in this function. I noticed that the current log document was named xxx.1 when the log was scrolling, but the log was still being written, resulting in a null pointer to fd.
What "scrolling"? Do you want to say "rotation"?
As long as rotating_file_sink_mt is used, no rotation should occur during file writing.
How can I reproduce this?
Yes, what I meant was rotation. To reproduce this scenario, it is necessary to write at a very high frequency. I created a log object using rotating_logger_mt function, and my creation code is as follows:
logger_ = spdlog::rotating_logger_mt("Logger", log_filename.c_str(), 1024 * 1024 * 20, 50);
logger_->flush_on(spdlog::level::debug);
My scenario is that high-frequency logging is performed within 32 threads, and then a crash occurs after rotating four log files.
I don't see why fd would be invalid for that use.
Do you use one logger for all threads?
yes ,the logger is Singleton pattern
I honestly don't know how to reproduce it. Is there a minimum code that can be reproduced? This is because an exception during rotation is notified to the error handler and should not cause a crash. https://github.com/gabime/spdlog/wiki/Error-handling
This is how I use the logging library: { Logger() { // std::string log_filename = "logs/" + getLogFilename(); logger_ = spdlog::rotating_logger_mt("Logger", log_filename.c_str(), 1024 * 1024 * 10, 50); logger_->flush_on(spdlog::level::debug);
std::string tick_foldername = "logs/tick";
std::string tick_filename = tick_foldername + "/" + getLogFilename();
tickLog_ = spdlog::rotating_logger_mt("Tick", tick_filename.c_str(), 1024 * 1024 * 10, 50);
tickLog_->flush_on(spdlog::level::debug);
console_ = spdlog::stdout_color_mt("console");
}
std::string getLogFilename() {
std::time_t t = std::time(nullptr);
std::tm tm = *std::localtime(&t);
char buffer[64];
std::strftime(buffer, sizeof(buffer), "%Y-%m-%d.log", &tm);
return buffer;
}
} Started 32 threads for heavy logging and crashed after a few minutes When the crash occurs,After the current xxx.1 xxx.2 xxx.3 and other files, there is no original xxx log file
The problem occurs because every time a Logger object is created, the spdlog logger that writes to the same file is created.
Do not create multiple spdlog loggers that write to the same file.
static Logger& getInstance() { static Logger instance; return instance; } The log object is accessed in a singleton mode. So there won't be the multiple creation problem you mentioned
If the function body of Logger::getInstance() is written in a header file, then the Logger object is created multiple times.
See:
- https://github.com/gabime/spdlog/issues/2267#issuecomment-1031930768
- https://stackoverflow.com/questions/18860895/how-to-initialize-static-members-in-the-header
When the crash occurs,After the current xxx.1 xxx.2 xxx.3 and other files, there is no original xxx log file
This situation can occur when an error is reported in the following source code.
https://github.com/gabime/spdlog/blob/57a9fd0841f00e92b478a07fef62636d7be612a8/include/spdlog/sinks/rotating_file_sink-inl.h#L124-L137
In Windows, renaming may fail for some reason (often anti-virus software).
If the rename fails, the log file is opened again, but if this is also intercepted by anti-virus software, fd becomes nullptr.
Note
fdisnullptrbecause the log file is closed before renaming.
In this case, the error handler is invoked by throw, so you can check the output of STDERR to see if you are encountering this problem (https://github.com/gabime/spdlog/wiki/Error-handling).
This problem cannot fix. If you are using anti-virus software, please exclude the log file from protection.
See also: https://stackoverflow.com/questions/33637513/unreliable-file-system-operations-on-windows
崩溃时,当前xxx.1 xxx.2 xxx.3等文件后,没有原来的xxx日志文件
当下面的源代码报错时,就会出现这种情况。
https://github.com/gabime/spdlog/blob/57a9fd0841f00e92b478a07fef62636d7be612a8/include/spdlog/sinks/rotating_file_sink-inl.h#L124-L137
在 Windows 中,由于某些原因(通常是杀毒软件),重命名可能会失败。 如果重命名失败,则重新打开日志文件,但如果这也被杀毒软件拦截,则
fd变成nullptr.注意
fd是nullptr因为日志文件在重命名之前已关闭。在这种情况下,错误处理程序由 调用
throw,因此您可以检查 的输出STDERR以查看您是否遇到此问题 ( https://github.com/gabime/spdlog/wiki/Error-handling )。这个问题无法修复。 如果您正在使用防病毒软件,请将日志文件排除在保护之外。
另请参阅:https ://stackoverflow.com/questions/33637513/unreliable-file-system-operations-on-windows
In my current environment under Linux, this problem appears steadily, and crashes after re-rotating 3 files
I can't determine the cause of the problem, so I'm going to report the error handler.
EDIT: File system problems are often reported in Windows OS, but similar problems can occur in Linux OS if anti-virus software is installed.
I can't determine the cause of the problem, so I'm going to report the error handler.
EDIT: File system problems are often reported in Windows OS, but similar problems can occur in Linux OS if anti-virus software is installed.
I went back to a two year old version of the spdlog code and the problem didn't happen again.
I went back to a two year old version of the spdlog code and the problem didn't happen again.
We cannot fix the bug unless we know the cause of the bug.
I will locate the specific cause of the problem, we will contact later