spdlog icon indicating copy to clipboard operation
spdlog copied to clipboard

rotating_logger_mt crashed

Open 18328594608 opened this issue 2 years ago • 15 comments

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.

18328594608 avatar May 06 '23 09:05 18328594608

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?

tt4g avatar May 06 '23 10:05 tt4g

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.

18328594608 avatar May 08 '23 01:05 18328594608

I don't see why fd would be invalid for that use. Do you use one logger for all threads?

tt4g avatar May 08 '23 02:05 tt4g

yes ,the logger is Singleton pattern

18328594608 avatar May 08 '23 05:05 18328594608

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

tt4g avatar May 08 '23 05:05 tt4g

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

18328594608 avatar May 08 '23 06:05 18328594608

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.

tt4g avatar May 08 '23 06:05 tt4g

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

18328594608 avatar May 08 '23 06:05 18328594608

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

tt4g avatar May 08 '23 07:05 tt4g

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 fd is nullptr because 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

tt4g avatar May 08 '23 08:05 tt4g

崩溃时,当前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.

注意 fdnullptr因为日志文件在重命名之前已关闭。

在这种情况下,错误处理程序由 调用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

18328594608 avatar May 08 '23 08:05 18328594608

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.

tt4g avatar May 08 '23 08:05 tt4g

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.

18328594608 avatar May 08 '23 09:05 18328594608

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.

tt4g avatar May 08 '23 09:05 tt4g

I will locate the specific cause of the problem, we will contact later

18328594608 avatar May 08 '23 09:05 18328594608