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