Line data Source code
1 : //
2 : // Copyright (c) 2017 Juniper Networks, Inc. All rights reserved.
3 : //
4 :
5 : #include <sys/wait.h>
6 :
7 : #include <boost/bind/bind.hpp>
8 : #include <boost/foreach.hpp>
9 : #include <boost/range/adaptor/map.hpp>
10 :
11 : #include <base/logging.h>
12 : #include <io/event_manager.h>
13 : #include <io/process_signal.h>
14 :
15 : using namespace boost::placeholders;
16 :
17 : namespace process {
18 :
19 46 : Signal::Signal(EventManager *evm,
20 : const SignalCallbackMap &sig_callback_map,
21 : const std::vector<SignalChildHandler> &sigchld_callbacks,
22 46 : bool always_handle_sigchild) :
23 46 : signal_(*(evm->io_service())),
24 46 : sig_callback_map_(sig_callback_map),
25 46 : sigchld_callbacks_(sigchld_callbacks),
26 46 : always_handle_sigchild_(always_handle_sigchild) {
27 46 : Initialize();
28 46 : }
29 :
30 2 : Signal::Signal(EventManager *evm,
31 2 : const SignalCallbackMap &sig_callback_map) :
32 2 : signal_(*(evm->io_service())),
33 2 : sig_callback_map_(sig_callback_map),
34 2 : sigchld_callbacks_(std::vector<SignalChildHandler>()),
35 2 : always_handle_sigchild_(false) {
36 2 : Initialize();
37 2 : }
38 :
39 48 : Signal::~Signal() {
40 48 : }
41 :
42 96 : boost::system::error_code Signal::AddSignal(int sig) {
43 96 : boost::system::error_code ec;
44 96 : signal_.add(sig, ec);
45 96 : if (ec) {
46 0 : std::string sigstr(strsignal(sig));
47 0 : LOG(ERROR, sigstr << " registration failed: " << ec);
48 0 : }
49 96 : return ec;
50 : }
51 :
52 2 : void Signal::RegisterHandler(int sig, SignalHandler handler) {
53 2 : SignalCallbackMap::iterator it = sig_callback_map_.find(sig);
54 2 : if (it == sig_callback_map_.end()) {
55 : // Add signal first
56 2 : AddSignal(sig);
57 2 : sig_callback_map_.insert(std::make_pair(sig,
58 4 : std::vector<SignalHandler>(1, handler)));
59 : } else {
60 0 : std::vector<SignalHandler> &sig_handlers(it->second);
61 0 : sig_handlers.push_back(handler);
62 : }
63 2 : }
64 :
65 1 : void Signal::NotifySigChld(const boost::system::error_code &error, int sig,
66 : int pid, int status) {
67 3 : BOOST_FOREACH(const SignalChildHandler &sh, sigchld_callbacks_) {
68 1 : sh(error, sig, pid, status);
69 : }
70 1 : }
71 :
72 46 : void Signal::NotifySig(const boost::system::error_code &error,
73 : int sig) {
74 46 : SignalCallbackMap::const_iterator it = sig_callback_map_.find(sig);
75 46 : if (it == sig_callback_map_.end()) {
76 0 : return;
77 : }
78 46 : const std::vector<SignalHandler> &callbacks(it->second);
79 138 : BOOST_FOREACH(const SignalHandler &sh, callbacks) {
80 46 : sh(error, sig);
81 : }
82 : }
83 :
84 0 : int Signal::WaitPid(int pid, int *status, int options) {
85 0 : return ::waitpid(pid, status, options);
86 : }
87 :
88 47 : void Signal::HandleSig(const boost::system::error_code &error, int sig) {
89 47 : if (!error) {
90 47 : if (!HandleSigOsSpecific(error, sig)) {
91 46 : NotifySig(error, sig);
92 : }
93 47 : RegisterSigHandler();
94 : }
95 47 : }
96 :
97 95 : void Signal::RegisterSigHandler() {
98 95 : signal_.async_wait(boost::bind(&Signal::HandleSig, this, _1, _2));
99 95 : }
100 :
101 48 : void Signal::Initialize() {
102 48 : boost::system::error_code ec;
103 :
104 : // Add signals
105 232 : BOOST_FOREACH(int sig, sig_callback_map_ | boost::adaptors::map_keys) {
106 92 : ec = AddSignal(sig);
107 : }
108 :
109 48 : ec = InitializeSigChild();
110 :
111 48 : RegisterSigHandler();
112 48 : }
113 :
114 46 : void Signal::Terminate() {
115 46 : boost::system::error_code ec;
116 46 : signal_.cancel(ec);
117 46 : signal_.clear(ec);
118 46 : }
119 :
120 : } // namespace process
|