23 #include <sys/eventfd.h> 24 #include <sys/signalfd.h> 34 ::pthread_sigmask(SIG_BLOCK, new_mask, old_mask);
39 ::sigprocmask(SIG_BLOCK, new_mask, old_mask);
57 SignalTrap(
Scope scope, std::initializer_list<core::posix::Signal> blocked_signals)
59 state(
State::not_running),
60 event_fd(::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK))
63 throw std::system_error(errno, std::system_category());
65 ::sigemptyset(&blocked_signals_mask);
67 for(
auto signal : blocked_signals)
68 ::sigaddset(&blocked_signals_mask, static_cast<int>(signal));
98 return ::sigismember(&blocked_signals_mask, static_cast<int>(signal));
103 static constexpr
int signal_fd_idx = 0;
104 static constexpr
int event_fd_idx = 1;
106 static constexpr
int signal_info_buffer_size = 5;
109 throw std::runtime_error(
"SignalTrap::run can only be run once.");
124 } scope{::signalfd(-1, &blocked_signals_mask, SFD_CLOEXEC | SFD_NONBLOCK)};
126 if (scope.signal_fd == -1)
127 throw std::system_error(errno, std::system_category());
130 signalfd_siginfo signal_info[signal_info_buffer_size];
134 fds[signal_fd_idx] = {scope.signal_fd, POLLIN, 0};
135 fds[event_fd_idx] = {event_fd, POLLIN, 0};
137 auto rc = ::poll(fds, 2, -1);
150 if (fds[signal_fd_idx].revents & POLLIN)
152 auto result = ::read(scope.signal_fd, signal_info,
sizeof(signal_info));
154 for (uint i = 0; i < result /
sizeof(signalfd_siginfo); i++)
156 if (
has(static_cast<core::posix::Signal>(signal_info[i].ssi_signo)))
159 static_cast<core::posix::Signal>(
160 signal_info[i].ssi_signo));
165 if (fds[event_fd_idx].revents & POLLIN)
167 std::int64_t value{1};
170 auto result = ::read(event_fd, &value,
sizeof(value));
182 static const std::int64_t value = {1};
183 if (
sizeof(value) != ::write(event_fd, &value,
sizeof(value)))
184 throw std::system_error(errno, std::system_category());
189 return on_signal_raised;
194 std::atomic<State> state;
196 core::Signal<core::posix::Signal> on_signal_raised;
197 ::sigset_t old_signals_mask;
198 ::sigset_t blocked_signals_mask;
203 std::initializer_list<core::posix::Signal> blocked_signals)
205 return std::make_shared<impl::SignalTrap>(
211 std::initializer_list<core::posix::Signal> blocked_signals)
213 return std::make_shared<impl::SignalTrap>(
SignalTrap(Scope scope, std::initializer_list< core::posix::Signal > blocked_signals)
bool has(core::posix::Signal signal) override
Returns true if the given signal is trapped by this instance.
core::Signal< core::posix::Signal > & signal_raised() override
Emitted whenever a trapped signal is raised by the operating system.
CORE_POSIX_DLL_PUBLIC std::shared_ptr< SignalTrap > trap_signals_for_process(std::initializer_list< core::posix::Signal > blocked_signals)
Traps the specified signals for the entire process.
void set_process_signal_mask(::sigset_t *new_mask,::sigset_t *old_mask)
Signal
The Signal enum collects the most common POSIX signals.
The SignalTrap class encapsulates functionality to trap and handle signals.
void run() override
Starts observation of incoming signals, relaying them via signal_raised(). The call blocks until stop...
CORE_POSIX_DLL_PUBLIC std::shared_ptr< SignalTrap > trap_signals_for_all_subsequent_threads(std::initializer_list< core::posix::Signal > blocked_signals)
Traps the specified signals for the current thread, and inherits the respective signal mask to all ch...
void stop() override
Stops execution of the signal trap.
void set_thread_signal_mask(::sigset_t *new_mask,::sigset_t *old_mask)