X-Git-Url: https://gerrit.akraino.org/r/gitweb?a=blobdiff_plain;f=src%2Ftype3_AndroidCloud%2Fanbox-master%2Fexternal%2Fprocess-cpp-minimal%2Fsrc%2Fcore%2Fposix%2Fsignal.cpp;fp=src%2Ftype3_AndroidCloud%2Fanbox-master%2Fexternal%2Fprocess-cpp-minimal%2Fsrc%2Fcore%2Fposix%2Fsignal.cpp;h=bcbbac8ab85649cf7b040a105734b428c879c6cf;hb=e26c1ec581be598521517829adba8c8dd23a768f;hp=0000000000000000000000000000000000000000;hpb=6699c1aea74eeb0eb400e6299079f0c7576f716f;p=iec.git diff --git a/src/type3_AndroidCloud/anbox-master/external/process-cpp-minimal/src/core/posix/signal.cpp b/src/type3_AndroidCloud/anbox-master/external/process-cpp-minimal/src/core/posix/signal.cpp new file mode 100644 index 0000000..bcbbac8 --- /dev/null +++ b/src/type3_AndroidCloud/anbox-master/external/process-cpp-minimal/src/core/posix/signal.cpp @@ -0,0 +1,221 @@ +/* + * Copyright © 2013 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Authored by: Thomas Voß + */ + +#include + +#include +#include +#include +#include + +#include + +#include + +namespace impl +{ +void set_thread_signal_mask(::sigset_t* new_mask, ::sigset_t* old_mask) +{ + ::pthread_sigmask(SIG_BLOCK, new_mask, old_mask); +} + +void set_process_signal_mask(::sigset_t* new_mask, ::sigset_t* old_mask) +{ + ::sigprocmask(SIG_BLOCK, new_mask, old_mask); +} + +class SignalTrap : public core::posix::SignalTrap +{ +public: + enum class Scope + { + process, + thread + }; + + enum class State + { + not_running, + running + }; + + SignalTrap(Scope scope, std::initializer_list blocked_signals) + : scope(scope), + state(State::not_running), + event_fd(::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)) + { + if (event_fd == -1) + throw std::system_error(errno, std::system_category()); + + ::sigemptyset(&blocked_signals_mask); + + for(auto signal : blocked_signals) + ::sigaddset(&blocked_signals_mask, static_cast(signal)); + + switch (scope) + { + case Scope::process: + set_process_signal_mask(&blocked_signals_mask, &old_signals_mask); + break; + case Scope::thread: + set_thread_signal_mask(&blocked_signals_mask, &old_signals_mask); + break; + default: + break; + } + } + + ~SignalTrap() + { + switch (scope) + { + case Scope::process: + set_process_signal_mask(&old_signals_mask, nullptr); + break; + case Scope::thread: + set_thread_signal_mask(&old_signals_mask, nullptr); + break; + default: + break; + } + + ::close(event_fd); + } + + bool has(core::posix::Signal signal) override + { + return ::sigismember(&blocked_signals_mask, static_cast(signal)); + } + + void run() override + { + static constexpr int signal_fd_idx = 0; + static constexpr int event_fd_idx = 1; + + static constexpr int signal_info_buffer_size = 5; + + if (state.load() == State::running) + throw std::runtime_error("SignalTrap::run can only be run once."); + + state.store(State::running); + + // Make sure we clean up the signal fd whenever + // we leave the scope of run. + struct Scope + { + ~Scope() + { + if (signal_fd != -1) + ::close(signal_fd); + } + + int signal_fd; + } scope{::signalfd(-1, &blocked_signals_mask, SFD_CLOEXEC | SFD_NONBLOCK)}; + + if (scope.signal_fd == -1) + throw std::system_error(errno, std::system_category()); + + pollfd fds[2]; + signalfd_siginfo signal_info[signal_info_buffer_size]; + + for (;;) + { + fds[signal_fd_idx] = {scope.signal_fd, POLLIN, 0}; + fds[event_fd_idx] = {event_fd, POLLIN, 0}; + + auto rc = ::poll(fds, 2, -1); + + if (rc == -1) + { + if (errno == EINTR) + continue; + + break; + } + + if (rc == 0) + continue; + + if (fds[signal_fd_idx].revents & POLLIN) + { + auto result = ::read(scope.signal_fd, signal_info, sizeof(signal_info)); + + for (unsigned int i = 0; i < result / sizeof(signalfd_siginfo); i++) + { + if (has(static_cast(signal_info[i].ssi_signo))) + { + on_signal_raised( + static_cast( + signal_info[i].ssi_signo)); + } + } + } + + if (fds[event_fd_idx].revents & POLLIN) + { + std::int64_t value{1}; + // Consciously void-ing the return value here. + // Not much we can do about an error. + auto result = ::read(event_fd, &value, sizeof(value)); + (void) result; + + break; + } + } + + state.store(State::not_running); + } + + void stop() override + { + static const std::int64_t value = {1}; + if (sizeof(value) != ::write(event_fd, &value, sizeof(value))) + throw std::system_error(errno, std::system_category()); + } + + core::Signal& signal_raised() override + { + return on_signal_raised; + } + +private: + Scope scope; + std::atomic state; + int event_fd; + core::Signal on_signal_raised; + ::sigset_t old_signals_mask; + ::sigset_t blocked_signals_mask; +}; +} + +std::shared_ptr core::posix::trap_signals_for_process( + std::initializer_list blocked_signals) +{ + return std::make_shared( + impl::SignalTrap::Scope::process, + blocked_signals); +} + +std::shared_ptr core::posix::trap_signals_for_all_subsequent_threads( + std::initializer_list blocked_signals) +{ + return std::make_shared( + impl::SignalTrap::Scope::thread, + blocked_signals); +} +