forked from ros2/rclcpp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsignal_handler.hpp
More file actions
189 lines (162 loc) · 5.06 KB
/
signal_handler.hpp
File metadata and controls
189 lines (162 loc) · 5.06 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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// Copyright 2018 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RCLCPP__SIGNAL_HANDLER_HPP_
#define RCLCPP__SIGNAL_HANDLER_HPP_
#include <atomic>
#include <csignal>
#include <mutex>
#include <thread>
#include "rclcpp/logging.hpp"
// includes for semaphore notification code
#if defined(_WIN32)
#include <windows.h>
#elif defined(__APPLE__)
#include <dispatch/dispatch.h>
#else // posix
#include <semaphore.h>
#endif
// Determine if sigaction is available
#if __APPLE__ || _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE
#define RCLCPP_HAS_SIGACTION
#endif
namespace rclcpp
{
/// Responsible for manaaging the SIGINT signal handling.
/**
* This class is responsible for:
*
* - installing the signal handler for SIGINT
* - uninstalling the signal handler for SIGINT
* - creating a thread to execute "on sigint" work outside of the signal handler
* - safely notifying the dedicated signal handling thread when receiving SIGINT
* - implementation of all of the signal handling work, like shutting down contexts
*
* \internal
*/
class SignalHandler final
{
public:
/// Return the global singleton of this class.
static
SignalHandler &
get_global_signal_handler();
/// Return a global singleton logger to avoid needing to create it everywhere.
static
rclcpp::Logger &
get_logger();
/// Install the signal handler for SIGINT and start the dedicated signal handling thread.
/**
* Also stores the current signal handler to be called on SIGINT and to
* restore when uninstalling this signal handler.
*/
bool
install();
/// Uninstall the signal handler for SIGINT and join the dedicated singal handling thread.
/**
* Also restores the previous signal handler.
*/
bool
uninstall();
/// Return true if installed, false otherwise.
bool
is_installed();
private:
SignalHandler() = default;
~SignalHandler();
#if defined(RCLCPP_HAS_SIGACTION)
using signal_handler_type = struct sigaction;
#else
using signal_handler_type = void (*)(int);
#endif
// POSIX signal handler structure storage for the existing signal handler.
static SignalHandler::signal_handler_type old_signal_handler_;
/// Set the signal handler function.
static
SignalHandler::signal_handler_type
set_signal_handler(int signal_value, const SignalHandler::signal_handler_type & signal_handler);
/// Common signal handler code between sigaction and non-sigaction versions.
static
void
signal_handler_common();
#if defined(RCLCPP_HAS_SIGACTION)
/// Signal handler function.
static
void
signal_handler(int signal_value, siginfo_t * siginfo, void * context);
#else
/// Signal handler function.
static
void
signal_handler(int signal_value);
#endif
/// Target of the dedicated signal handling thread.
void
deferred_signal_handler();
/// Setup anything that is necessary for wait_for_signal() or notify_signal_handler().
/**
* This must be called before wait_for_signal() or notify_signal_handler().
* This is not thread-safe.
*/
static
void
setup_wait_for_signal();
/// Undo all setup done in setup_wait_for_signal().
/**
* Must not call wait_for_signal() or notify_signal_handler() after calling this.
*
* This is not thread-safe.
*/
static
void
teardown_wait_for_signal() noexcept;
/// Wait for a notification from notify_signal_handler() in a signal safe way.
/**
* This static method may throw if posting the semaphore fails.
*
* This is not thread-safe.
*/
static
void
wait_for_signal();
/// Notify blocking wait_for_signal() calls in a signal safe way.
/**
* This is used to notify the deferred_signal_handler() thread to start work
* from the signal handler.
*
* This is thread-safe.
*/
static
void
notify_signal_handler() noexcept;
// Whether or not a signal has been received.
static std::atomic_bool signal_received_;
// A thread to which singal handling tasks are deferred.
std::thread signal_handler_thread_;
// A mutex used to synchronize the install() and uninstall() methods.
std::mutex install_mutex_;
// Whether or not the signal handler has been installed.
std::atomic_bool installed_{false};
// Whether or not the semaphore for wait_for_signal is setup.
static std::atomic_bool wait_for_signal_is_setup_;
// Storage for the wait_for_signal semaphore.
#if defined(_WIN32)
static HANDLE signal_handler_sem_;
#elif defined(__APPLE__)
static dispatch_semaphore_t signal_handler_sem_;
#else // posix
static sem_t signal_handler_sem_;
#endif
};
} // namespace rclcpp
#endif // RCLCPP__SIGNAL_HANDLER_HPP_