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