20#include <freerdp/config.h>
28#include <freerdp/utils/signal.h>
29#include <freerdp/log.h>
36#define TAG FREERDP_TAG("utils.signal")
40int freerdp_handle_signals(
void)
46BOOL freerdp_add_signal_cleanup_handler(
void* context, freerdp_signal_handler_t fkt)
51BOOL freerdp_del_signal_cleanup_handler(
void* context, freerdp_signal_handler_t fkt)
58#include <winpr/debug.h>
60static BOOL handlers_registered = FALSE;
61static pthread_mutex_t signal_handler_lock = PTHREAD_MUTEX_INITIALIZER;
66 freerdp_signal_handler_t handler;
69static size_t cleanup_handler_count = 0;
70static cleanup_handler_t cleanup_handlers[20] = { 0 };
74 const int rc = pthread_mutex_lock(&signal_handler_lock);
77 char ebuffer[256] = { 0 };
78 WLog_ERR(TAG,
"[pthread_mutex_lock] failed with %s [%d]",
79 winpr_strerror(rc, ebuffer,
sizeof(ebuffer)), rc);
83static void unlock(
void)
85 const int rc = pthread_mutex_unlock(&signal_handler_lock);
88 char ebuffer[256] = { 0 };
89 WLog_ERR(TAG,
"[pthread_mutex_lock] failed with %s [%d]",
90 winpr_strerror(rc, ebuffer,
sizeof(ebuffer)), rc);
94static void term_handler(
int signum)
96 static BOOL recursive = FALSE;
102 WLog_ERR(TAG,
"Caught signal '%s' [%d]", strsignal(signum), signum);
106 for (
size_t x = 0; x < cleanup_handler_count; x++)
108 const cleanup_handler_t empty = { 0 };
109 cleanup_handler_t* cur = &cleanup_handlers[x];
113 cur->handler(signum, strsignal(signum), cur->context);
117 cleanup_handler_count = 0;
121static void fatal_handler(
int signum)
123 struct sigaction default_sigaction;
125 static BOOL recursive = FALSE;
131 WLog_ERR(TAG,
"Caught signal '%s' [%d]", strsignal(signum), signum);
133 winpr_log_backtrace(TAG, WLOG_ERROR, 20);
136 default_sigaction.sa_handler = SIG_DFL;
137 sigfillset(&(default_sigaction.sa_mask));
138 default_sigaction.sa_flags = 0;
139 sigaction(signum, &default_sigaction, NULL);
140 sigemptyset(&this_mask);
141 sigaddset(&this_mask, signum);
142 pthread_sigmask(SIG_UNBLOCK, &this_mask, NULL);
146static const int term_signals[] = { SIGINT, SIGKILL, SIGQUIT, SIGSTOP, SIGTERM };
148static const int fatal_signals[] = { SIGABRT, SIGALRM, SIGBUS, SIGFPE, SIGHUP, SIGILL,
149 SIGSEGV, SIGTTIN, SIGTTOU, SIGUSR1, SIGUSR2,
165static BOOL register_handlers(
const int* signals,
size_t count,
void (*handler)(
int))
167 WINPR_ASSERT(signals || (count == 0));
168 WINPR_ASSERT(handler);
170 sigset_t orig_set = { 0 };
171 struct sigaction saction = { 0 };
173 pthread_sigmask(SIG_BLOCK, &(saction.sa_mask), &orig_set);
175 sigfillset(&(saction.sa_mask));
176 sigdelset(&(saction.sa_mask), SIGCONT);
178 saction.sa_handler = handler;
179 saction.sa_flags = 0;
181 for (
size_t x = 0; x < count; x++)
183 struct sigaction orig_sigaction = { 0 };
184 if (sigaction(signals[x], NULL, &orig_sigaction) == 0)
186 if (orig_sigaction.sa_handler != SIG_IGN)
188 sigaction(signals[x], &saction, NULL);
193 pthread_sigmask(SIG_SETMASK, &orig_set, NULL);
198int freerdp_handle_signals(
void)
204 WLog_DBG(TAG,
"Registering signal hook...");
206 if (!register_handlers(fatal_signals, ARRAYSIZE(fatal_signals), fatal_handler))
208 if (!register_handlers(term_signals, ARRAYSIZE(term_signals), term_handler))
212 (void)signal(SIGPIPE, SIG_IGN);
213 handlers_registered = TRUE;
220BOOL freerdp_add_signal_cleanup_handler(
void* context, freerdp_signal_handler_t handler)
224 if (handlers_registered)
226 if (cleanup_handler_count < ARRAYSIZE(cleanup_handlers))
228 cleanup_handler_t* cur = &cleanup_handlers[cleanup_handler_count++];
229 cur->context = context;
230 cur->handler = handler;
233 WLog_WARN(TAG,
"Failed to register cleanup handler, only %" PRIuz
" handlers supported",
234 ARRAYSIZE(cleanup_handlers));
241BOOL freerdp_del_signal_cleanup_handler(
void* context, freerdp_signal_handler_t handler)
245 if (handlers_registered)
247 for (
size_t x = 0; x < cleanup_handler_count; x++)
249 cleanup_handler_t* cur = &cleanup_handlers[x];
250 if ((cur->context == context) && (cur->handler == handler))
252 const cleanup_handler_t empty = { 0 };
253 for (
size_t y = x + 1; y < cleanup_handler_count - 1; y++)
255 *cur++ = cleanup_handlers[y];
259 cleanup_handler_count--;