Make logger thread safe (#885)

This commit is contained in:
Murat Seker
2020-07-19 15:37:47 +02:00
committed by GitHub
parent 45303e1b64
commit 4880e31562
10 changed files with 276 additions and 193 deletions

View File

@@ -16,6 +16,35 @@
namespace DefaultSignalHandler
{
struct Signal
{
int number;
const char * name;
};
const Signal ALL_SIGNALS[] = {
{ SIGABRT, "SIGABRT" },
{ SIGBUS, "SIGBUS" },
{ SIGFPE, "SIGFPE" },
{ SIGILL, "SIGILL" },
{ SIGSEGV, "SIGSEGV" },
{ SIGTERM, "SIGTERM" },
{ SIGHUP, "SIGHUP" },
{ SIGINT, "SIGINT" },
{ SIGPIPE, "SIGPIPE" },
};
void write_to_stderr(const char* data, size_t size)
{
int res = write(STDERR_FILENO, data, size);
Q_UNUSED(res);
}
void write_to_stderr(const char* data)
{
write_to_stderr(data, strlen(data));
}
std::string decipher_trace(const std::string &trace)
{
@@ -70,26 +99,48 @@ void print_trace()
free(symbols);
}
void install_default_handler(int signum)
{
struct sigaction action{};
sigemptyset(&action.sa_mask);
action.sa_handler = SIG_DFL;
(void)sigaction(signum, &action, nullptr);
}
/* Note that this signal handler is not async signal safe !
* Ideally a signal handler should only flip a bit and defer
* heavy work to some kind of bottom-half processing. */
void signal_handler(int signum, siginfo_t * /*info*/, void * /*context*/)
{
Logger* log = Logger::getInstance("SIGNAL");
const char * name = "UNKNOWN SIGNAL";
char *name = strsignal(signum);
if (name)
{
Info(log, "Signal received : %s", name);
for (const auto& s : ALL_SIGNALS) {
if (s.number == signum) {
name = s.name;
break;
}
}
write_to_stderr("\n");
write_to_stderr("Hyperion caught signal :");
write_to_stderr(name);
write_to_stderr("\n");
/* Anything below here is unsafe ! */
switch(signum)
{
case SIGBUS:
case SIGSEGV:
case SIGABRT:
case SIGFPE :
print_trace();
exit(1);
/* Don't catch our own signal */
install_default_handler(signum);
kill(getpid(), signum);
return;
case SIGINT :
case SIGTERM:
case SIGPIPE:
@@ -101,10 +152,7 @@ void signal_handler(int signum, siginfo_t * /*info*/, void * /*context*/)
QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection);
// Reset signal handler to default (in case this handler is not capable of stopping)
struct sigaction action{};
action.sa_handler = SIG_DFL;
sigaction(signum, &action, nullptr);
install_default_handler(signum);
}
}
@@ -116,17 +164,20 @@ namespace DefaultSignalHandler
void install()
{
#ifndef _WIN32
struct sigaction action{};
action.sa_sigaction = signal_handler;
action.sa_flags = SA_RESTART | SA_SIGINFO;
Logger* log = Logger::getInstance("CORE");
sigaction(SIGHUP , &action, nullptr);
sigaction(SIGFPE , &action, nullptr);
sigaction(SIGINT , &action, nullptr);
sigaction(SIGTERM, &action, nullptr);
sigaction(SIGABRT, &action, nullptr);
sigaction(SIGSEGV, &action, nullptr);
sigaction(SIGPIPE, &action, nullptr);
struct sigaction action{};
sigemptyset(&action.sa_mask);
action.sa_sigaction = signal_handler;
action.sa_flags |= SA_SIGINFO;
for (const auto& s : ALL_SIGNALS)
{
if (sigaction(s.number, &action, nullptr)!= 0)
{
Error(log, "Failed to install handler for %s]\n", s.name);
}
}
#endif // _WIN32
}
} // namespace DefaultSignalHandler