Line data Source code
1 : // Copyright (c) 2012-2021 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/eventdispatcher
4 : // contact@m2osw.com
5 : //
6 : // This program is free software; you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation; either version 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License
17 : // along with this program; if not, write to the Free Software
18 : // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 : #pragma once
20 :
21 : /** \file
22 : * \brief Event dispatch class.
23 : *
24 : * Functions used to setup how unrecoverable Unix signals should be
25 : * handled.
26 : */
27 :
28 : // cppthread lib
29 : //
30 : #include <cppthread/mutex.h>
31 :
32 :
33 : // C++ lib
34 : //
35 : #include <functional>
36 : #include <list>
37 : #include <memory>
38 :
39 :
40 : // C lib
41 : //
42 : #include <signal.h>
43 :
44 :
45 :
46 : namespace ed
47 : {
48 :
49 :
50 :
51 : class signal_handler
52 : {
53 : public:
54 : typedef std::shared_ptr<signal_handler> pointer_t;
55 : typedef std::uint64_t signal_mask_t;
56 : typedef std::uint32_t callback_id_t;
57 : typedef std::function<bool(
58 : callback_id_t callback_id
59 : , int callback_sig
60 : , siginfo_t const * info
61 : , ucontext_t const * ucontext)> callback_t;
62 :
63 : static constexpr signal_mask_t const SIGNAL_HANGUP = 1UL << SIGHUP;
64 : static constexpr signal_mask_t const SIGNAL_INTERRUPT = 1UL << SIGINT;
65 : static constexpr signal_mask_t const SIGNAL_QUIT = 1UL << SIGQUIT;
66 : static constexpr signal_mask_t const SIGNAL_ILLEGAL = 1UL << SIGILL;
67 : static constexpr signal_mask_t const SIGNAL_TRAP = 1UL << SIGTRAP;
68 : static constexpr signal_mask_t const SIGNAL_ABORT = 1UL << SIGABRT; // SIGIOT
69 : static constexpr signal_mask_t const SIGNAL_BUS = 1UL << SIGBUS;
70 : static constexpr signal_mask_t const SIGNAL_FLOATPOINTERROR = 1UL << SIGFPE;
71 : static constexpr signal_mask_t const SIGNAL_KILL = 1UL << SIGKILL;
72 : static constexpr signal_mask_t const SIGNAL_USR1 = 1UL << SIGUSR1;
73 : static constexpr signal_mask_t const SIGNAL_SEGMENTVIOLATION = 1UL << SIGSEGV;
74 : static constexpr signal_mask_t const SIGNAL_USR2 = 1UL << SIGUSR2;
75 : static constexpr signal_mask_t const SIGNAL_PIPE = 1UL << SIGPIPE;
76 : static constexpr signal_mask_t const SIGNAL_ALARM = 1UL << SIGALRM;
77 : static constexpr signal_mask_t const SIGNAL_TERMINATE = 1UL << SIGTERM; // Ctrl-C
78 : static constexpr signal_mask_t const SIGNAL_STACK_FAULT = 1UL << SIGSTKFLT;
79 : static constexpr signal_mask_t const SIGNAL_CHILD = 1UL << SIGCHLD;
80 : static constexpr signal_mask_t const SIGNAL_CONTINUE = 1UL << SIGCONT; // Ctrl-Q
81 : static constexpr signal_mask_t const SIGNAL_STOP = 1UL << SIGSTOP; // Ctrl-S
82 : static constexpr signal_mask_t const SIGNAL_INTERACTIVE_STOP = 1UL << SIGTSTP;
83 : static constexpr signal_mask_t const SIGNAL_TERMINAL_IN = 1UL << SIGTTIN; // Ctrl-Z
84 : static constexpr signal_mask_t const SIGNAL_TERMINAL_OUT = 1UL << SIGTTOU;
85 : static constexpr signal_mask_t const SIGNAL_URGENT = 1UL << SIGURG;
86 : static constexpr signal_mask_t const SIGNAL_XCPU = 1UL << SIGXCPU;
87 : static constexpr signal_mask_t const SIGNAL_FILE_SIZE = 1UL << SIGXFSZ;
88 : static constexpr signal_mask_t const SIGNAL_VIRTUAL_ALARM = 1UL << SIGVTALRM;
89 : static constexpr signal_mask_t const SIGNAL_PROFILING = 1UL << SIGPROF;
90 : static constexpr signal_mask_t const SIGNAL_WINDOW_CHANGE = 1UL << SIGWINCH;
91 : static constexpr signal_mask_t const SIGNAL_POLL = 1UL << SIGPOLL; // SIGIO/SIGLOST
92 : static constexpr signal_mask_t const SIGNAL_POWER = 1UL << SIGPWR;
93 : static constexpr signal_mask_t const SIGNAL_SYSTEM = 1UL << SIGSYS;
94 :
95 : static constexpr signal_mask_t const ALL_SIGNALS = 0xFFFFFFFFFFFFFFFEUL;
96 : static constexpr signal_mask_t const DEFAULT_SIGNAL_TERMINAL =
97 : SIGNAL_ILLEGAL
98 : | SIGNAL_BUS
99 : | SIGNAL_FLOATPOINTERROR
100 : | SIGNAL_SEGMENTVIOLATION;
101 : static constexpr signal_mask_t const EXTENDED_SIGNAL_TERMINAL =
102 : DEFAULT_SIGNAL_TERMINAL
103 : | SIGNAL_INTERRUPT
104 : | SIGNAL_QUIT
105 : | SIGNAL_TERMINATE;
106 : static constexpr signal_mask_t const DEFAULT_SIGNAL_IGNORE =
107 : SIGNAL_INTERACTIVE_STOP
108 : | SIGNAL_TERMINAL_IN
109 : | SIGNAL_TERMINAL_OUT
110 : | SIGNAL_PIPE;
111 :
112 : static constexpr signal_mask_t const DEFAULT_SHOW_STACK =
113 : ALL_SIGNALS
114 : & ~(SIGNAL_ALARM
115 : | SIGNAL_CHILD
116 : | SIGNAL_HANGUP
117 : | SIGNAL_INTERRUPT
118 : | SIGNAL_PIPE
119 : | SIGNAL_POLL
120 : | SIGNAL_PROFILING
121 : | SIGNAL_QUIT
122 : | SIGNAL_TERMINATE
123 : | SIGNAL_URGENT
124 : | SIGNAL_WINDOW_CHANGE
125 : | SIGNAL_XCPU);
126 :
127 : signal_handler(signal_handler const &) = delete;
128 : ~signal_handler();
129 :
130 : signal_handler & operator = (signal_handler const &) = delete;
131 :
132 : static pointer_t create_instance(
133 : signal_mask_t terminal = DEFAULT_SIGNAL_TERMINAL
134 : , signal_mask_t ignored = DEFAULT_SIGNAL_IGNORE
135 : , callback_id_t callback_id = -1
136 : , int callback_sig = -1
137 : , callback_t callback = callback_t());
138 : static pointer_t get_instance();
139 :
140 : void add_callback(callback_id_t id, int sig, callback_t callback);
141 : void remove_callback(callback_id_t id);
142 : void set_show_stack(signal_mask_t sigs);
143 : signal_mask_t get_show_stack() const;
144 : void add_terminal_signals(signal_mask_t sigs);
145 : void add_ignored_signals(signal_mask_t sigs);
146 : void remove_signals(signal_mask_t sigs);
147 : void remove_all_signals();
148 : static char const * get_signal_name(int sig);
149 :
150 : private:
151 0 : struct signal_callback_t
152 : {
153 : callback_id_t f_id = -1;
154 : int f_sig = -1;
155 : callback_t f_callback = nullptr;
156 : };
157 : typedef std::list<signal_callback_t> callback_list_t;
158 : typedef struct sigaction sigaction_t;
159 : typedef std::shared_ptr<sigaction_t> sigaction_ptr_t;
160 :
161 : signal_handler();
162 : static void signal_handler_func(int sig, siginfo_t * info, void * context);
163 : void process_signal(int sig, siginfo_t * info, ucontext_t * ucontext);
164 :
165 : mutable cppthread::mutex f_mutex = cppthread::mutex();
166 : sigaction_ptr_t f_signal_actions[64] = { sigaction_ptr_t() };
167 : callback_list_t f_callbacks = callback_list_t();
168 : };
169 :
170 :
171 :
172 : } // namespace ed
173 : // vim: ts=4 sw=4 et
|