7#include <winpr/atexit.h>
9#include <winpr/debug.h>
11#include <freerdp/log.h>
12#include <freerdp/utils/signal.h>
14#include "platform_signal.h"
16#define TAG FREERDP_TAG("utils.signal.posix")
18static pthread_mutex_t signal_handler_lock = PTHREAD_MUTEX_INITIALIZER;
22 const int rc = pthread_mutex_lock(&signal_handler_lock);
25 char ebuffer[256] = WINPR_C_ARRAY_INIT;
26 WLog_ERR(TAG,
"[pthread_mutex_lock] failed with %s [%d]",
27 winpr_strerror(rc, ebuffer,
sizeof(ebuffer)), rc);
33 const int rc = pthread_mutex_unlock(&signal_handler_lock);
36 char ebuffer[256] = WINPR_C_ARRAY_INIT;
37 WLog_ERR(TAG,
"[pthread_mutex_lock] failed with %s [%d]",
38 winpr_strerror(rc, ebuffer,
sizeof(ebuffer)), rc);
42static void fatal_handler(
int signum)
44 struct sigaction default_sigaction;
46 static BOOL recursive = FALSE;
52 WLog_ERR(TAG,
"Caught signal '%s' [%d]", strsignal(signum), signum);
54 winpr_log_backtrace(TAG, WLOG_ERROR, 20);
57 default_sigaction.sa_handler = SIG_DFL;
58 sigfillset(&(default_sigaction.sa_mask));
59 default_sigaction.sa_flags = 0;
60 sigaction(signum, &default_sigaction,
nullptr);
61 sigemptyset(&this_mask);
62 sigaddset(&this_mask, signum);
63 pthread_sigmask(SIG_UNBLOCK, &this_mask,
nullptr);
67static const int term_signals[] = { SIGINT, SIGKILL, SIGQUIT, SIGSTOP, SIGTERM };
69static const int fatal_signals[] = { SIGABRT, SIGALRM, SIGBUS, SIGFPE, SIGHUP,
70 SIGILL, SIGSEGV, SIGTTIN, SIGTTOU,
86static BOOL register_handlers(
const int* signals,
size_t count,
void (*handler)(
int))
88 WINPR_ASSERT(signals || (count == 0));
89 WINPR_ASSERT(handler);
91 sigset_t orig_set = WINPR_C_ARRAY_INIT;
92 struct sigaction saction = WINPR_C_ARRAY_INIT;
94 pthread_sigmask(SIG_BLOCK, &(saction.sa_mask), &orig_set);
96 sigfillset(&(saction.sa_mask));
97 sigdelset(&(saction.sa_mask), SIGCONT);
99 saction.sa_handler = handler;
100 saction.sa_flags = 0;
102 for (
size_t x = 0; x < count; x++)
104 struct sigaction orig_sigaction = WINPR_C_ARRAY_INIT;
105 if (sigaction(signals[x],
nullptr, &orig_sigaction) == 0)
107 if (orig_sigaction.sa_handler != SIG_IGN)
109 sigaction(signals[x], &saction,
nullptr);
114 pthread_sigmask(SIG_SETMASK, &orig_set,
nullptr);
119static void unregister_handlers(
const int* signals,
size_t count)
121 WINPR_ASSERT(signals || (count == 0));
123 sigset_t orig_set = WINPR_C_ARRAY_INIT;
124 struct sigaction saction = WINPR_C_ARRAY_INIT;
126 pthread_sigmask(SIG_BLOCK, &(saction.sa_mask), &orig_set);
128 sigfillset(&(saction.sa_mask));
129 sigdelset(&(saction.sa_mask), SIGCONT);
131 saction.sa_handler = SIG_IGN;
132 saction.sa_flags = 0;
134 for (
size_t x = 0; x < count; x++)
136 sigaction(signals[x], &saction,
nullptr);
139 pthread_sigmask(SIG_SETMASK, &orig_set,
nullptr);
142static void unregister_all_handlers(
void)
144 unregister_handlers(fatal_signals, ARRAYSIZE(fatal_signals));
145 unregister_handlers(term_signals, ARRAYSIZE(term_signals));
148int freerdp_handle_signals(
void)
154 WLog_DBG(TAG,
"Registering signal hook...");
156 (void)winpr_atexit(unregister_all_handlers);
157 if (!register_handlers(fatal_signals, ARRAYSIZE(fatal_signals), fatal_handler))
159 if (!register_handlers(term_signals, ARRAYSIZE(term_signals), fsig_term_handler))
163 (void)signal(SIGPIPE, SIG_IGN);
164 fsig_handlers_registered = TRUE;