mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2025-03-01 10:33:28 +00:00
Make logger thread safe (#885)
This commit is contained in:
@@ -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
|
||||
|
Reference in New Issue
Block a user