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