FreeRDP
Loading...
Searching...
No Matches
signal_win32.c
1#include <stddef.h>
2#include <errno.h>
3#include <signal.h>
4
5#include <winpr/atexit.h>
6#include <winpr/wlog.h>
7#include <winpr/debug.h>
8#include <winpr/assert.h>
9
10#include <freerdp/log.h>
11#include <freerdp/utils/signal.h>
12
13#include "platform_signal.h"
14
15#define TAG FREERDP_TAG("utils.signal.posix")
16
17static CRITICAL_SECTION signal_lock;
18static INIT_ONCE signal_lock_init = INIT_ONCE_STATIC_INIT;
19
20static BOOL CALLBACK init_signal_lock(PINIT_ONCE InitOnce, PVOID Parameter, PVOID* Context)
21{
22 InitializeCriticalSection(&signal_lock);
23 return TRUE;
24}
25
26void fsig_lock(void)
27{
28 InitOnceExecuteOnce(&signal_lock_init, init_signal_lock, NULL, NULL);
29 EnterCriticalSection(&signal_lock);
30}
31
32void fsig_unlock(void)
33{
34 LeaveCriticalSection(&signal_lock);
35}
36
37const char* strsignal(int signum)
38{
39#define CASE_STR(x) \
40 case x: \
41 return #x
42 switch (signum)
43 {
44 CASE_STR(SIGINT);
45 CASE_STR(SIGILL);
46 CASE_STR(SIGFPE);
47 CASE_STR(SIGSEGV);
48 CASE_STR(SIGTERM);
49 CASE_STR(SIGBREAK);
50 CASE_STR(SIGABRT);
51 CASE_STR(SIGABRT_COMPAT);
52 default:
53 return "SIG_UNKNOWN";
54 }
55}
56static void fatal_handler(int signum)
57{
58 static BOOL recursive = FALSE;
59
60 if (!recursive)
61 {
62 recursive = TRUE;
63 // NOLINTNEXTLINE(concuSWSrrency-mt-unsafe)
64 WLog_ERR(TAG, "Caught signal '%s' [%d]", strsignal(signum), signum);
65
66 winpr_log_backtrace(TAG, WLOG_ERROR, 20);
67 }
68
69 (void)raise(signum);
70}
71
72static const int term_signals[] = { SIGINT, SIGTERM };
73
74static const int fatal_signals[] = { SIGABRT, SIGFPE, SIGILL, SIGSEGV };
75
76static BOOL register_handlers(const int* signals, size_t count, void (*handler)(int))
77{
78 WINPR_ASSERT(signals || (count == 0));
79 WINPR_ASSERT(handler);
80
81 for (size_t x = 0; x < count; x++)
82 {
83 (void)signal(signals[x], handler);
84 }
85
86 return TRUE;
87}
88
89static void unregister_handlers(const int* signals, size_t count)
90{
91 WINPR_ASSERT(signals || (count == 0));
92
93 for (size_t x = 0; x < count; x++)
94 {
95 (void)signal(signals[x], SIG_IGN);
96 }
97}
98
99static void unregister_all_handlers(void)
100{
101 unregister_handlers(fatal_signals, ARRAYSIZE(fatal_signals));
102 unregister_handlers(term_signals, ARRAYSIZE(term_signals));
103 DeleteCriticalSection(&signal_lock);
104}
105
106int freerdp_handle_signals(void)
107{
108 int rc = -1;
109 fsig_lock();
110
111 WLog_DBG(TAG, "Registering signal hook...");
112
113 (void)winpr_atexit(unregister_all_handlers);
114 if (!register_handlers(fatal_signals, ARRAYSIZE(fatal_signals), fatal_handler))
115 goto fail;
116 if (!register_handlers(term_signals, ARRAYSIZE(term_signals), fsig_term_handler))
117 goto fail;
118
119 fsig_handlers_registered = true;
120 rc = 0;
121fail:
122 fsig_unlock();
123 return rc;
124}