8#include <winpr/debug.h>
10#include <freerdp/log.h>
11#include <freerdp/utils/signal.h>
13#include "platform_signal.h"
15#define TAG FREERDP_TAG("utils.signal.posix")
17static pthread_mutex_t signal_handler_lock = PTHREAD_MUTEX_INITIALIZER;
21 const int rc = pthread_mutex_lock(&signal_handler_lock);
24 char ebuffer[256] = { 0 };
25 WLog_ERR(TAG,
"[pthread_mutex_lock] failed with %s [%d]",
26 winpr_strerror(rc, ebuffer,
sizeof(ebuffer)), rc);
32 const int rc = pthread_mutex_unlock(&signal_handler_lock);
35 char ebuffer[256] = { 0 };
36 WLog_ERR(TAG,
"[pthread_mutex_lock] failed with %s [%d]",
37 winpr_strerror(rc, ebuffer,
sizeof(ebuffer)), rc);
41static void fatal_handler(
int signum)
43 struct sigaction default_sigaction;
45 static BOOL recursive = FALSE;
51 WLog_ERR(TAG,
"Caught signal '%s' [%d]", strsignal(signum), signum);
53 winpr_log_backtrace(TAG, WLOG_ERROR, 20);
56 default_sigaction.sa_handler = SIG_DFL;
57 sigfillset(&(default_sigaction.sa_mask));
58 default_sigaction.sa_flags = 0;
59 sigaction(signum, &default_sigaction, NULL);
60 sigemptyset(&this_mask);
61 sigaddset(&this_mask, signum);
62 pthread_sigmask(SIG_UNBLOCK, &this_mask, NULL);
66static const int term_signals[] = { SIGINT, SIGKILL, SIGQUIT, SIGSTOP, SIGTERM };
68static const int fatal_signals[] = { SIGABRT, SIGALRM, SIGBUS, SIGFPE, SIGHUP,
69 SIGILL, SIGSEGV, SIGTTIN, SIGTTOU,
85static BOOL register_handlers(
const int* signals,
size_t count,
void (*handler)(
int))
87 WINPR_ASSERT(signals || (count == 0));
88 WINPR_ASSERT(handler);
90 sigset_t orig_set = { 0 };
91 struct sigaction saction = { 0 };
93 pthread_sigmask(SIG_BLOCK, &(saction.sa_mask), &orig_set);
95 sigfillset(&(saction.sa_mask));
96 sigdelset(&(saction.sa_mask), SIGCONT);
98 saction.sa_handler = handler;
101 for (
size_t x = 0; x < count; x++)
103 struct sigaction orig_sigaction = { 0 };
104 if (sigaction(signals[x], NULL, &orig_sigaction) == 0)
106 if (orig_sigaction.sa_handler != SIG_IGN)
108 sigaction(signals[x], &saction, NULL);
113 pthread_sigmask(SIG_SETMASK, &orig_set, NULL);
118static void unregister_handlers(
const int* signals,
size_t count)
120 WINPR_ASSERT(signals || (count == 0));
122 sigset_t orig_set = { 0 };
123 struct sigaction saction = { 0 };
125 pthread_sigmask(SIG_BLOCK, &(saction.sa_mask), &orig_set);
127 sigfillset(&(saction.sa_mask));
128 sigdelset(&(saction.sa_mask), SIGCONT);
130 saction.sa_handler = SIG_IGN;
131 saction.sa_flags = 0;
133 for (
size_t x = 0; x < count; x++)
135 sigaction(signals[x], &saction, NULL);
138 pthread_sigmask(SIG_SETMASK, &orig_set, NULL);
141static void unregister_all_handlers(
void)
143 unregister_handlers(fatal_signals, ARRAYSIZE(fatal_signals));
144 unregister_handlers(term_signals, ARRAYSIZE(term_signals));
147int freerdp_handle_signals(
void)
153 WLog_DBG(TAG,
"Registering signal hook...");
155 (void)atexit(unregister_all_handlers);
156 if (!register_handlers(fatal_signals, ARRAYSIZE(fatal_signals), fatal_handler))
158 if (!register_handlers(term_signals, ARRAYSIZE(term_signals), fsig_term_handler))
162 (void)signal(SIGPIPE, SIG_IGN);
163 fsig_handlers_registered = TRUE;