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,
 
  149                                   SIGILL,    SIGSEGV, SIGTTIN, SIGTTOU,
 
  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--;