1 // 2 // detail/signal_set_service.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 // 7 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 // 10 11 #ifndef BOOST_ASIO_DETAIL_SIGNAL_SET_SERVICE_HPP 12 #define BOOST_ASIO_DETAIL_SIGNAL_SET_SERVICE_HPP 13 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 15 # pragma once 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18 #include <boost/asio/detail/config.hpp> 19 20 #include <cstddef> 21 #include <signal.h> 22 #include <boost/asio/error.hpp> 23 #include <boost/asio/execution_context.hpp> 24 #include <boost/asio/detail/handler_alloc_helpers.hpp> 25 #include <boost/asio/detail/memory.hpp> 26 #include <boost/asio/detail/op_queue.hpp> 27 #include <boost/asio/detail/signal_handler.hpp> 28 #include <boost/asio/detail/signal_op.hpp> 29 #include <boost/asio/detail/socket_types.hpp> 30 31 #if defined(BOOST_ASIO_HAS_IOCP) 32 # include <boost/asio/detail/win_iocp_io_context.hpp> 33 #else // defined(BOOST_ASIO_HAS_IOCP) 34 # include <boost/asio/detail/scheduler.hpp> 35 #endif // defined(BOOST_ASIO_HAS_IOCP) 36 37 #if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) 38 # include <boost/asio/detail/reactor.hpp> 39 #endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) 40 41 #include <boost/asio/detail/push_options.hpp> 42 43 namespace boost { 44 namespace asio { 45 namespace detail { 46 47 #if defined(NSIG) && (NSIG > 0) 48 enum { max_signal_number = NSIG }; 49 #else 50 enum { max_signal_number = 128 }; 51 #endif 52 53 extern BOOST_ASIO_DECL struct signal_state* get_signal_state(); 54 55 extern "C" BOOST_ASIO_DECL void boost_asio_signal_handler(int signal_number); 56 57 class signal_set_service : 58 public execution_context_service_base<signal_set_service> 59 { 60 public: 61 // Type used for tracking an individual signal registration. 62 class registration 63 { 64 public: 65 // Default constructor. registration()66 registration() 67 : signal_number_(0), 68 queue_(0), 69 undelivered_(0), 70 next_in_table_(0), 71 prev_in_table_(0), 72 next_in_set_(0) 73 { 74 } 75 76 private: 77 // Only this service will have access to the internal values. 78 friend class signal_set_service; 79 80 // The signal number that is registered. 81 int signal_number_; 82 83 // The waiting signal handlers. 84 op_queue<signal_op>* queue_; 85 86 // The number of undelivered signals. 87 std::size_t undelivered_; 88 89 // Pointers to adjacent registrations in the registrations_ table. 90 registration* next_in_table_; 91 registration* prev_in_table_; 92 93 // Link to next registration in the signal set. 94 registration* next_in_set_; 95 }; 96 97 // The implementation type of the signal_set. 98 class implementation_type 99 { 100 public: 101 // Default constructor. implementation_type()102 implementation_type() 103 : signals_(0) 104 { 105 } 106 107 private: 108 // Only this service will have access to the internal values. 109 friend class signal_set_service; 110 111 // The pending signal handlers. 112 op_queue<signal_op> queue_; 113 114 // Linked list of registered signals. 115 registration* signals_; 116 }; 117 118 // Constructor. 119 BOOST_ASIO_DECL signal_set_service(execution_context& context); 120 121 // Destructor. 122 BOOST_ASIO_DECL ~signal_set_service(); 123 124 // Destroy all user-defined handler objects owned by the service. 125 BOOST_ASIO_DECL void shutdown(); 126 127 // Perform fork-related housekeeping. 128 BOOST_ASIO_DECL void notify_fork( 129 boost::asio::execution_context::fork_event fork_ev); 130 131 // Construct a new signal_set implementation. 132 BOOST_ASIO_DECL void construct(implementation_type& impl); 133 134 // Destroy a signal_set implementation. 135 BOOST_ASIO_DECL void destroy(implementation_type& impl); 136 137 // Add a signal to a signal_set. 138 BOOST_ASIO_DECL boost::system::error_code add(implementation_type& impl, 139 int signal_number, boost::system::error_code& ec); 140 141 // Remove a signal to a signal_set. 142 BOOST_ASIO_DECL boost::system::error_code remove(implementation_type& impl, 143 int signal_number, boost::system::error_code& ec); 144 145 // Remove all signals from a signal_set. 146 BOOST_ASIO_DECL boost::system::error_code clear(implementation_type& impl, 147 boost::system::error_code& ec); 148 149 // Cancel all operations associated with the signal set. 150 BOOST_ASIO_DECL boost::system::error_code cancel(implementation_type& impl, 151 boost::system::error_code& ec); 152 153 // Start an asynchronous operation to wait for a signal to be delivered. 154 template <typename Handler, typename IoExecutor> async_wait(implementation_type & impl,Handler & handler,const IoExecutor & io_ex)155 void async_wait(implementation_type& impl, 156 Handler& handler, const IoExecutor& io_ex) 157 { 158 // Allocate and construct an operation to wrap the handler. 159 typedef signal_handler<Handler, IoExecutor> op; 160 typename op::ptr p = { boost::asio::detail::addressof(handler), 161 op::ptr::allocate(handler), 0 }; 162 p.p = new (p.v) op(handler, io_ex); 163 164 BOOST_ASIO_HANDLER_CREATION((scheduler_.context(), 165 *p.p, "signal_set", &impl, 0, "async_wait")); 166 167 start_wait_op(impl, p.p); 168 p.v = p.p = 0; 169 } 170 171 // Deliver notification that a particular signal occurred. 172 BOOST_ASIO_DECL static void deliver_signal(int signal_number); 173 174 private: 175 // Helper function to add a service to the global signal state. 176 BOOST_ASIO_DECL static void add_service(signal_set_service* service); 177 178 // Helper function to remove a service from the global signal state. 179 BOOST_ASIO_DECL static void remove_service(signal_set_service* service); 180 181 // Helper function to create the pipe descriptors. 182 BOOST_ASIO_DECL static void open_descriptors(); 183 184 // Helper function to close the pipe descriptors. 185 BOOST_ASIO_DECL static void close_descriptors(); 186 187 // Helper function to start a wait operation. 188 BOOST_ASIO_DECL void start_wait_op(implementation_type& impl, signal_op* op); 189 190 // The scheduler used for dispatching handlers. 191 #if defined(BOOST_ASIO_HAS_IOCP) 192 typedef class win_iocp_io_context scheduler_impl; 193 #else 194 typedef class scheduler scheduler_impl; 195 #endif 196 scheduler_impl& scheduler_; 197 198 #if !defined(BOOST_ASIO_WINDOWS) \ 199 && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ 200 && !defined(__CYGWIN__) 201 // The type used for registering for pipe reactor notifications. 202 class pipe_read_op; 203 204 // The reactor used for waiting for pipe readiness. 205 reactor& reactor_; 206 207 // The per-descriptor reactor data used for the pipe. 208 reactor::per_descriptor_data reactor_data_; 209 #endif // !defined(BOOST_ASIO_WINDOWS) 210 // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) 211 // && !defined(__CYGWIN__) 212 213 // A mapping from signal number to the registered signal sets. 214 registration* registrations_[max_signal_number]; 215 216 // Pointers to adjacent services in linked list. 217 signal_set_service* next_; 218 signal_set_service* prev_; 219 }; 220 221 } // namespace detail 222 } // namespace asio 223 } // namespace boost 224 225 #include <boost/asio/detail/pop_options.hpp> 226 227 #if defined(BOOST_ASIO_HEADER_ONLY) 228 # include <boost/asio/detail/impl/signal_set_service.ipp> 229 #endif // defined(BOOST_ASIO_HEADER_ONLY) 230 231 #endif // BOOST_ASIO_DETAIL_SIGNAL_SET_SERVICE_HPP 232