-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsig.cpp
More file actions
145 lines (122 loc) · 3.57 KB
/
sig.cpp
File metadata and controls
145 lines (122 loc) · 3.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include "sig.h"
#include <mutex>
#include <atomic>
#include <unordered_map>
static std::recursive_mutex _mutex;
#define LOCK() std::scoped_lock<decltype(_mutex)> f_lock(_mutex)
static std::unordered_map<sig::signals, sighandler_t> default_handlers;
static std::unordered_map<sig::signals, std::vector<sig::signal_handler_type>> signal_handlers;
static std::unordered_map<sig::signals, sig::signal_handler_type> temporary_handlers;
static sig::Settings sig_settings;
static bool sig_IS_SIGNAL_FATAL(int signal)
{
auto sg = static_cast<sig::signals>(signal);
// If we can find the signal in the 'fatal_signals' set, then it's fatal!
return sig_settings.fatal_signals.find(sg) != sig_settings.fatal_signals.end();
}
static void sig_SIGNAL_HANDLER(int signal)
{
LOCK();
auto f_signal = static_cast<sig::signals>(signal);
auto found_tmp = temporary_handlers.find(f_signal);
if(found_tmp != temporary_handlers.end())
{
auto func = found_tmp->second;
if(func)
{
func(signal);
}
return;
}
auto found_handlers = signal_handlers.find(f_signal);
if(found_handlers != signal_handlers.end())
{
auto& handlers = found_handlers->second;
auto size = handlers.size();
for(auto i = 0; i < size; ++i)
{
auto func = handlers[i];
if(func)
{
func(signal);
}
}
}
if(sig_IS_SIGNAL_FATAL(signal))
{
auto base_handler = default_handlers.find(f_signal);
if(base_handler != default_handlers.end())
{
auto handler = base_handler->second;
if(handler)
{
// Re-insert the original handler and raise the signal
std::signal(signal, handler);
std::raise(signal);
}
else
{
// TODO - Log Error?
}
}
else
{
// TODO - Log Error?
}
// TODO - Better handling?
exit(128 + signal);
}
}
void sig::initialize(sig::Settings settings) noexcept
{
static std::atomic_bool isInitialized(false);
if(!isInitialized)
{
isInitialized = true;
sig_settings = std::move(settings);
for(sig::signals sg : ALL_SIGNALS)
{
auto default_handler = std::signal(static_cast<int>(sg), sig_SIGNAL_HANDLER);
default_handlers.emplace(sg, default_handler);
}
}
}
void sig::push_signal_handler(const sig::signal_handler_type& func, sig::signals signal)
{
LOCK();
auto& handlers = signal_handlers[signal];
handlers.emplace_back(func);
}
void sig::push_signal_handler(const sig::signal_handler_type& func, const std::set<sig::signals>& signals)
{
LOCK();
for(sig::signals sg : signals)
{
auto& handlers = signal_handlers[sg];
handlers.emplace_back(func);
}
}
void sig::push_temporary_handler(const sig::signal_handler_type &func, sig::signals signal)
{
if(temporary_handlers.find(signal) == temporary_handlers.end())
{
temporary_handlers[signal] = func;
}
}
sig::signal_handler_type sig::pop_temporary_handler(sig::signals signal)
{
if(temporary_handlers.find(signal) == temporary_handlers.end())
{
return nullptr;
}
else
{
auto tmp = temporary_handlers[signal];
temporary_handlers.erase(signal);
return tmp;
}
}
bool sig::is_temporary_handler_populated(sig::signals signal)
{
return temporary_handlers.find(signal) != temporary_handlers.end();
}