spdlog icon indicating copy to clipboard operation
spdlog copied to clipboard

Provide way to gracefully terminate or use spdlog in signal handlers

Open TamasFlorin opened this issue 5 years ago • 7 comments
trafficstars

Hey,

First of all, thank your for all the work that you have put into this!

I was wondering what is the right way of handling the following situation: we are using the async logger and the process suddenly crashes without having the chance to flush the log messages to the file.

My first thought was to install a signal handler for SIGSEGV and SIGABRT and call spdlog::shutdown() from the respective handler. However, the shutdown method does not seem to be async-safe since it uses std::mutex, meaning that this could cause deadlocks when the process crashes and that might be even worse than losing a few logs.

Are there any other suggestions that could help us get around this issue?

Thanks

TamasFlorin avatar Jul 07 '20 06:07 TamasFlorin

There are not many safe operations within the signal handler (see reference: std::signal - cppreference.com). And spdlog does not support its use within signal handlers.

One workaround is to use std::condition_variable to call a function that is not signal safe outside the signal function. Like this link example code, if you call the notification function of std::condition_variable in the signal function and call spdlog::shutdown() when the process thread receives the notification, spdlog will now shutdown when a signal is received.

tt4g avatar Jul 07 '20 09:07 tt4g

First of all, thank your for all the work that you have put into this!

Thanks for the feedback :)

I will add it to the todo list to implement in spdlog somehow (probably similar to @tt4g suggestion).

gabime avatar Jul 07 '20 12:07 gabime

First of all, thank your for all the work that you have put into this!

Thanks for the feedback :)

I will add it to the todo list to implement in spdlog somehow (probably similar to @tt4g suggestion).

Thank you @gabime ! Looking forward to it!

TamasFlorin avatar Jul 07 '20 15:07 TamasFlorin

There are not many safe operations within the signal handler (see reference: std::signal - cppreference.com). And spdlog does not support its use within signal handlers.

One workaround is to use std::condition_variable to call a function that is not signal safe outside the signal function. Like this link example code, if you call the notification function of std::condition_variable in the signal function and call spdlog::shutdown() when the process thread receives the notification, spdlog will now shutdown when a signal is received.

Thanks for the suggestion @tt4g ! I will look into it.

TamasFlorin avatar Jul 07 '20 15:07 TamasFlorin

Could you please provide an example code snippet of how to implement logs flushing when segfault occurs?

qaler avatar Mar 09 '21 12:03 qaler

@qaler This is very simple example:

#include <atomic>
#include <csignal>
#include <iostream>

#include "spdlog/spdlog.h"

static std::atomic<bool> signalReceived = false;

void signal_handler(int signal)
{
    signalReceived = true;
}
 
int main()
{
    std::signal(SIGINT, signal_handler);

    for (;;) {
        if (signalReceived) {
            // Handle signal
            spdlog::error("Signal!!!");
            break;
        } else {
            // Main process.
            std::cout << "Main\n";
        }
    }
}

tt4g avatar Mar 10 '21 00:03 tt4g