mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-14 00:14:11 +09:00
[utils,signal] split handlers per platform
This commit is contained in:
@@ -28,6 +28,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
profiler.c
|
||||
ringbuffer.c
|
||||
signal.c
|
||||
signal.h
|
||||
string.c
|
||||
gfx.c
|
||||
drdynvc.c
|
||||
@@ -39,6 +40,12 @@ set(${MODULE_PREFIX}_SRCS
|
||||
http.c
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND ${MODULE_PREFIX}_SRCS signal_win32.c)
|
||||
else()
|
||||
list(APPEND ${MODULE_PREFIX}_SRCS signal_posix.c)
|
||||
endif()
|
||||
|
||||
freerdp_module_add(${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
freerdp_library_add(${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
@@ -19,46 +19,19 @@
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/debug.h>
|
||||
|
||||
#include <freerdp/utils/signal.h>
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
#endif
|
||||
#include "signal.h"
|
||||
|
||||
#define TAG FREERDP_TAG("utils.signal")
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
int freerdp_handle_signals(void)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
BOOL freerdp_add_signal_cleanup_handler(void* context, freerdp_signal_handler_t fkt)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL freerdp_del_signal_cleanup_handler(void* context, freerdp_signal_handler_t fkt)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
|
||||
#include <pthread.h>
|
||||
#include <winpr/debug.h>
|
||||
|
||||
static BOOL handlers_registered = FALSE;
|
||||
static pthread_mutex_t signal_handler_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
BOOL fsig_handlers_registered = FALSE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -69,29 +42,7 @@ typedef struct
|
||||
static size_t cleanup_handler_count = 0;
|
||||
static cleanup_handler_t cleanup_handlers[20] = { 0 };
|
||||
|
||||
static void lock(void)
|
||||
{
|
||||
const int rc = pthread_mutex_lock(&signal_handler_lock);
|
||||
if (rc != 0)
|
||||
{
|
||||
char ebuffer[256] = { 0 };
|
||||
WLog_ERR(TAG, "[pthread_mutex_lock] failed with %s [%d]",
|
||||
winpr_strerror(rc, ebuffer, sizeof(ebuffer)), rc);
|
||||
}
|
||||
}
|
||||
|
||||
static void unlock(void)
|
||||
{
|
||||
const int rc = pthread_mutex_unlock(&signal_handler_lock);
|
||||
if (rc != 0)
|
||||
{
|
||||
char ebuffer[256] = { 0 };
|
||||
WLog_ERR(TAG, "[pthread_mutex_lock] failed with %s [%d]",
|
||||
winpr_strerror(rc, ebuffer, sizeof(ebuffer)), rc);
|
||||
}
|
||||
}
|
||||
|
||||
static void term_handler(int signum)
|
||||
void fsig_term_handler(int signum)
|
||||
{
|
||||
static BOOL recursive = FALSE;
|
||||
|
||||
@@ -102,7 +53,7 @@ static void term_handler(int signum)
|
||||
WLog_ERR(TAG, "Caught signal '%s' [%d]", strsignal(signum), signum);
|
||||
}
|
||||
|
||||
lock();
|
||||
fsig_lock();
|
||||
for (size_t x = 0; x < cleanup_handler_count; x++)
|
||||
{
|
||||
const cleanup_handler_t empty = { 0 };
|
||||
@@ -115,143 +66,14 @@ static void term_handler(int signum)
|
||||
*cur = empty;
|
||||
}
|
||||
cleanup_handler_count = 0;
|
||||
unlock();
|
||||
}
|
||||
|
||||
static void fatal_handler(int signum)
|
||||
{
|
||||
struct sigaction default_sigaction;
|
||||
sigset_t this_mask;
|
||||
static BOOL recursive = FALSE;
|
||||
|
||||
if (!recursive)
|
||||
{
|
||||
recursive = TRUE;
|
||||
// NOLINTNEXTLINE(concurrency-mt-unsafe)
|
||||
WLog_ERR(TAG, "Caught signal '%s' [%d]", strsignal(signum), signum);
|
||||
|
||||
winpr_log_backtrace(TAG, WLOG_ERROR, 20);
|
||||
}
|
||||
|
||||
default_sigaction.sa_handler = SIG_DFL;
|
||||
sigfillset(&(default_sigaction.sa_mask));
|
||||
default_sigaction.sa_flags = 0;
|
||||
sigaction(signum, &default_sigaction, NULL);
|
||||
sigemptyset(&this_mask);
|
||||
sigaddset(&this_mask, signum);
|
||||
pthread_sigmask(SIG_UNBLOCK, &this_mask, NULL);
|
||||
(void)raise(signum);
|
||||
}
|
||||
|
||||
static const int term_signals[] = { SIGINT, SIGKILL, SIGQUIT, SIGSTOP, SIGTERM };
|
||||
|
||||
static const int fatal_signals[] = { SIGABRT, SIGALRM, SIGBUS, SIGFPE, SIGHUP,
|
||||
SIGILL, SIGSEGV, SIGTTIN, SIGTTOU,
|
||||
#ifdef SIGPOLL
|
||||
SIGPOLL,
|
||||
#endif
|
||||
#ifdef SIGPROF
|
||||
SIGPROF,
|
||||
#endif
|
||||
#ifdef SIGSYS
|
||||
SIGSYS,
|
||||
#endif
|
||||
SIGTRAP,
|
||||
#ifdef SIGVTALRM
|
||||
SIGVTALRM,
|
||||
#endif
|
||||
SIGXCPU, SIGXFSZ };
|
||||
|
||||
static BOOL register_handlers(const int* signals, size_t count, void (*handler)(int))
|
||||
{
|
||||
WINPR_ASSERT(signals || (count == 0));
|
||||
WINPR_ASSERT(handler);
|
||||
|
||||
sigset_t orig_set = { 0 };
|
||||
struct sigaction saction = { 0 };
|
||||
|
||||
pthread_sigmask(SIG_BLOCK, &(saction.sa_mask), &orig_set);
|
||||
|
||||
sigfillset(&(saction.sa_mask));
|
||||
sigdelset(&(saction.sa_mask), SIGCONT);
|
||||
|
||||
saction.sa_handler = handler;
|
||||
saction.sa_flags = 0;
|
||||
|
||||
for (size_t x = 0; x < count; x++)
|
||||
{
|
||||
struct sigaction orig_sigaction = { 0 };
|
||||
if (sigaction(signals[x], NULL, &orig_sigaction) == 0)
|
||||
{
|
||||
if (orig_sigaction.sa_handler != SIG_IGN)
|
||||
{
|
||||
sigaction(signals[x], &saction, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pthread_sigmask(SIG_SETMASK, &orig_set, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void unregister_handlers(const int* signals, size_t count)
|
||||
{
|
||||
WINPR_ASSERT(signals || (count == 0));
|
||||
|
||||
sigset_t orig_set = { 0 };
|
||||
struct sigaction saction = { 0 };
|
||||
|
||||
pthread_sigmask(SIG_BLOCK, &(saction.sa_mask), &orig_set);
|
||||
|
||||
sigfillset(&(saction.sa_mask));
|
||||
sigdelset(&(saction.sa_mask), SIGCONT);
|
||||
|
||||
saction.sa_handler = SIG_IGN;
|
||||
saction.sa_flags = 0;
|
||||
|
||||
for (size_t x = 0; x < count; x++)
|
||||
{
|
||||
sigaction(signals[x], &saction, NULL);
|
||||
}
|
||||
|
||||
pthread_sigmask(SIG_SETMASK, &orig_set, NULL);
|
||||
}
|
||||
|
||||
static void unregister_all_handlers(void)
|
||||
{
|
||||
unregister_handlers(fatal_signals, ARRAYSIZE(fatal_signals));
|
||||
unregister_handlers(term_signals, ARRAYSIZE(term_signals));
|
||||
}
|
||||
|
||||
int freerdp_handle_signals(void)
|
||||
{
|
||||
int rc = -1;
|
||||
|
||||
lock();
|
||||
|
||||
WLog_DBG(TAG, "Registering signal hook...");
|
||||
|
||||
(void)atexit(unregister_all_handlers);
|
||||
if (!register_handlers(fatal_signals, ARRAYSIZE(fatal_signals), fatal_handler))
|
||||
goto fail;
|
||||
if (!register_handlers(term_signals, ARRAYSIZE(term_signals), term_handler))
|
||||
goto fail;
|
||||
|
||||
/* Ignore SIGPIPE signal. */
|
||||
(void)signal(SIGPIPE, SIG_IGN);
|
||||
handlers_registered = TRUE;
|
||||
rc = 0;
|
||||
fail:
|
||||
unlock();
|
||||
return rc;
|
||||
fsig_unlock();
|
||||
}
|
||||
|
||||
BOOL freerdp_add_signal_cleanup_handler(void* context, freerdp_signal_handler_t handler)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
lock();
|
||||
if (handlers_registered)
|
||||
fsig_lock();
|
||||
if (fsig_handlers_registered)
|
||||
{
|
||||
if (cleanup_handler_count < ARRAYSIZE(cleanup_handlers))
|
||||
{
|
||||
@@ -264,15 +86,15 @@ BOOL freerdp_add_signal_cleanup_handler(void* context, freerdp_signal_handler_t
|
||||
ARRAYSIZE(cleanup_handlers));
|
||||
}
|
||||
rc = TRUE;
|
||||
unlock();
|
||||
fsig_unlock();
|
||||
return rc;
|
||||
}
|
||||
|
||||
BOOL freerdp_del_signal_cleanup_handler(void* context, freerdp_signal_handler_t handler)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
lock();
|
||||
if (handlers_registered)
|
||||
fsig_lock();
|
||||
if (fsig_handlers_registered)
|
||||
{
|
||||
for (size_t x = 0; x < cleanup_handler_count; x++)
|
||||
{
|
||||
@@ -292,8 +114,6 @@ BOOL freerdp_del_signal_cleanup_handler(void* context, freerdp_signal_handler_t
|
||||
}
|
||||
}
|
||||
rc = TRUE;
|
||||
unlock();
|
||||
fsig_unlock();
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
9
libfreerdp/utils/signal.h
Normal file
9
libfreerdp/utils/signal.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
extern BOOL fsig_handlers_registered;
|
||||
|
||||
void fsig_lock(void);
|
||||
void fsig_unlock(void);
|
||||
void fsig_term_handler(int signum);
|
||||
168
libfreerdp/utils/signal_posix.c
Normal file
168
libfreerdp/utils/signal_posix.c
Normal file
@@ -0,0 +1,168 @@
|
||||
#include <pthread.h>
|
||||
#include <stddef.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/debug.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/utils/signal.h>
|
||||
|
||||
#include "signal.h"
|
||||
|
||||
#define TAG FREERDP_TAG("utils.signal.posix")
|
||||
|
||||
static pthread_mutex_t signal_handler_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
void fsig_lock(void)
|
||||
{
|
||||
const int rc = pthread_mutex_lock(&signal_handler_lock);
|
||||
if (rc != 0)
|
||||
{
|
||||
char ebuffer[256] = { 0 };
|
||||
WLog_ERR(TAG, "[pthread_mutex_lock] failed with %s [%d]",
|
||||
winpr_strerror(rc, ebuffer, sizeof(ebuffer)), rc);
|
||||
}
|
||||
}
|
||||
|
||||
void fsig_unlock(void)
|
||||
{
|
||||
const int rc = pthread_mutex_unlock(&signal_handler_lock);
|
||||
if (rc != 0)
|
||||
{
|
||||
char ebuffer[256] = { 0 };
|
||||
WLog_ERR(TAG, "[pthread_mutex_lock] failed with %s [%d]",
|
||||
winpr_strerror(rc, ebuffer, sizeof(ebuffer)), rc);
|
||||
}
|
||||
}
|
||||
|
||||
static void fatal_handler(int signum)
|
||||
{
|
||||
struct sigaction default_sigaction;
|
||||
sigset_t this_mask;
|
||||
static BOOL recursive = FALSE;
|
||||
|
||||
if (!recursive)
|
||||
{
|
||||
recursive = TRUE;
|
||||
// NOLINTNEXTLINE(concurrency-mt-unsafe)
|
||||
WLog_ERR(TAG, "Caught signal '%s' [%d]", strsignal(signum), signum);
|
||||
|
||||
winpr_log_backtrace(TAG, WLOG_ERROR, 20);
|
||||
}
|
||||
|
||||
default_sigaction.sa_handler = SIG_DFL;
|
||||
sigfillset(&(default_sigaction.sa_mask));
|
||||
default_sigaction.sa_flags = 0;
|
||||
sigaction(signum, &default_sigaction, NULL);
|
||||
sigemptyset(&this_mask);
|
||||
sigaddset(&this_mask, signum);
|
||||
pthread_sigmask(SIG_UNBLOCK, &this_mask, NULL);
|
||||
(void)raise(signum);
|
||||
}
|
||||
|
||||
static const int term_signals[] = { SIGINT, SIGKILL, SIGQUIT, SIGSTOP, SIGTERM };
|
||||
|
||||
static const int fatal_signals[] = { SIGABRT, SIGALRM, SIGBUS, SIGFPE, SIGHUP,
|
||||
SIGILL, SIGSEGV, SIGTTIN, SIGTTOU,
|
||||
#ifdef SIGPOLL
|
||||
SIGPOLL,
|
||||
#endif
|
||||
#ifdef SIGPROF
|
||||
SIGPROF,
|
||||
#endif
|
||||
#ifdef SIGSYS
|
||||
SIGSYS,
|
||||
#endif
|
||||
SIGTRAP,
|
||||
#ifdef SIGVTALRM
|
||||
SIGVTALRM,
|
||||
#endif
|
||||
SIGXCPU, SIGXFSZ };
|
||||
|
||||
static BOOL register_handlers(const int* signals, size_t count, void (*handler)(int))
|
||||
{
|
||||
WINPR_ASSERT(signals || (count == 0));
|
||||
WINPR_ASSERT(handler);
|
||||
|
||||
sigset_t orig_set = { 0 };
|
||||
struct sigaction saction = { 0 };
|
||||
|
||||
pthread_sigmask(SIG_BLOCK, &(saction.sa_mask), &orig_set);
|
||||
|
||||
sigfillset(&(saction.sa_mask));
|
||||
sigdelset(&(saction.sa_mask), SIGCONT);
|
||||
|
||||
saction.sa_handler = handler;
|
||||
saction.sa_flags = 0;
|
||||
|
||||
for (size_t x = 0; x < count; x++)
|
||||
{
|
||||
struct sigaction orig_sigaction = { 0 };
|
||||
if (sigaction(signals[x], NULL, &orig_sigaction) == 0)
|
||||
{
|
||||
if (orig_sigaction.sa_handler != SIG_IGN)
|
||||
{
|
||||
sigaction(signals[x], &saction, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pthread_sigmask(SIG_SETMASK, &orig_set, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void unregister_handlers(const int* signals, size_t count)
|
||||
{
|
||||
WINPR_ASSERT(signals || (count == 0));
|
||||
|
||||
sigset_t orig_set = { 0 };
|
||||
struct sigaction saction = { 0 };
|
||||
|
||||
pthread_sigmask(SIG_BLOCK, &(saction.sa_mask), &orig_set);
|
||||
|
||||
sigfillset(&(saction.sa_mask));
|
||||
sigdelset(&(saction.sa_mask), SIGCONT);
|
||||
|
||||
saction.sa_handler = SIG_IGN;
|
||||
saction.sa_flags = 0;
|
||||
|
||||
for (size_t x = 0; x < count; x++)
|
||||
{
|
||||
sigaction(signals[x], &saction, NULL);
|
||||
}
|
||||
|
||||
pthread_sigmask(SIG_SETMASK, &orig_set, NULL);
|
||||
}
|
||||
|
||||
static void unregister_all_handlers(void)
|
||||
{
|
||||
unregister_handlers(fatal_signals, ARRAYSIZE(fatal_signals));
|
||||
unregister_handlers(term_signals, ARRAYSIZE(term_signals));
|
||||
}
|
||||
|
||||
int freerdp_handle_signals(void)
|
||||
{
|
||||
int rc = -1;
|
||||
|
||||
fsig_lock();
|
||||
|
||||
WLog_DBG(TAG, "Registering signal hook...");
|
||||
|
||||
(void)atexit(unregister_all_handlers);
|
||||
if (!register_handlers(fatal_signals, ARRAYSIZE(fatal_signals), fatal_handler))
|
||||
goto fail;
|
||||
if (!register_handlers(term_signals, ARRAYSIZE(term_signals), fsig_term_handler))
|
||||
goto fail;
|
||||
|
||||
/* Ignore SIGPIPE signal. */
|
||||
(void)signal(SIGPIPE, SIG_IGN);
|
||||
fsig_handlers_registered = TRUE;
|
||||
rc = 0;
|
||||
fail:
|
||||
fsig_unlock();
|
||||
return rc;
|
||||
}
|
||||
8
libfreerdp/utils/signal_win32.c
Normal file
8
libfreerdp/utils/signal_win32.c
Normal file
@@ -0,0 +1,8 @@
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
|
||||
int freerdp_handle_signals(void)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
Reference in New Issue
Block a user