20 #include <freerdp/config.h>
26 #include <winpr/crt.h>
28 #include <freerdp/utils/signal.h>
29 #include <freerdp/log.h>
36 #define TAG FREERDP_TAG("utils.signal")
40 int freerdp_handle_signals(
void)
46 BOOL freerdp_add_signal_cleanup_handler(
void* context, freerdp_signal_handler_t fkt)
51 BOOL freerdp_del_signal_cleanup_handler(
void* context, freerdp_signal_handler_t fkt)
58 #include <winpr/debug.h>
60 static BOOL handlers_registered = FALSE;
61 static pthread_mutex_t signal_handler_lock = PTHREAD_MUTEX_INITIALIZER;
66 freerdp_signal_handler_t handler;
69 static size_t cleanup_handler_count = 0;
70 static cleanup_handler_t cleanup_handlers[20] = { 0 };
72 static void lock(
void)
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);
83 static 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);
94 static void term_handler(
int signum)
96 static BOOL recursive = FALSE;
101 WLog_ERR(TAG,
"Caught signal '%s' [%d]", strsignal(signum), signum);
105 for (
size_t x = 0; x < cleanup_handler_count; x++)
107 const cleanup_handler_t empty = { 0 };
108 cleanup_handler_t* cur = &cleanup_handlers[x];
110 cur->handler(signum, strsignal(signum), cur->context);
113 cleanup_handler_count = 0;
117 static void fatal_handler(
int signum)
119 struct sigaction default_sigaction;
121 static BOOL recursive = FALSE;
126 WLog_ERR(TAG,
"Caught signal '%s' [%d]", strsignal(signum), signum);
128 winpr_log_backtrace(TAG, WLOG_ERROR, 20);
131 default_sigaction.sa_handler = SIG_DFL;
132 sigfillset(&(default_sigaction.sa_mask));
133 default_sigaction.sa_flags = 0;
134 sigaction(signum, &default_sigaction, NULL);
135 sigemptyset(&this_mask);
136 sigaddset(&this_mask, signum);
137 pthread_sigmask(SIG_UNBLOCK, &this_mask, NULL);
141 static const int term_signals[] = { SIGINT, SIGKILL, SIGQUIT, SIGSTOP, SIGTERM };
143 static const int fatal_signals[] = { SIGABRT, SIGALRM, SIGBUS, SIGFPE, SIGHUP, SIGILL,
144 SIGSEGV, SIGTSTP, SIGTTIN, SIGTTOU, SIGUSR1, SIGUSR2,
160 static BOOL register_handlers(
const int* signals,
size_t count,
void (*handler)(
int))
162 WINPR_ASSERT(signals || (count == 0));
163 WINPR_ASSERT(handler);
165 sigset_t orig_set = { 0 };
166 struct sigaction saction = { 0 };
168 pthread_sigmask(SIG_BLOCK, &(saction.sa_mask), &orig_set);
170 sigfillset(&(saction.sa_mask));
171 sigdelset(&(saction.sa_mask), SIGCONT);
173 saction.sa_handler = handler;
174 saction.sa_flags = 0;
176 for (
size_t x = 0; x < count; x++)
178 struct sigaction orig_sigaction = { 0 };
179 if (sigaction(signals[x], NULL, &orig_sigaction) == 0)
181 if (orig_sigaction.sa_handler != SIG_IGN)
183 sigaction(signals[x], &saction, NULL);
188 pthread_sigmask(SIG_SETMASK, &orig_set, NULL);
193 int freerdp_handle_signals(
void)
199 WLog_DBG(TAG,
"Registering signal hook...");
201 if (!register_handlers(fatal_signals, ARRAYSIZE(fatal_signals), fatal_handler))
203 if (!register_handlers(term_signals, ARRAYSIZE(term_signals), term_handler))
207 (void)signal(SIGPIPE, SIG_IGN);
208 handlers_registered = TRUE;
215 BOOL freerdp_add_signal_cleanup_handler(
void* context, freerdp_signal_handler_t handler)
219 if (handlers_registered)
221 if (cleanup_handler_count < ARRAYSIZE(cleanup_handlers))
223 cleanup_handler_t* cur = &cleanup_handlers[cleanup_handler_count++];
224 cur->context = context;
225 cur->handler = handler;
228 WLog_WARN(TAG,
"Failed to register cleanup handler, only %" PRIuz
" handlers supported",
229 ARRAYSIZE(cleanup_handlers));
236 BOOL freerdp_del_signal_cleanup_handler(
void* context, freerdp_signal_handler_t handler)
240 if (handlers_registered)
242 for (
size_t x = 0; x < cleanup_handler_count; x++)
244 cleanup_handler_t* cur = &cleanup_handlers[x];
245 if ((cur->context == context) && (cur->handler == handler))
247 const cleanup_handler_t empty = { 0 };
248 for (
size_t y = x + 1; y < cleanup_handler_count - 1; y++)
250 *cur++ = cleanup_handlers[y];
254 cleanup_handler_count--;