OpenSDN source code
process_signal_common.cc
Go to the documentation of this file.
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 Signal::Signal(EventManager *evm,
20  const SignalCallbackMap &sig_callback_map,
21  const std::vector<SignalChildHandler> &sigchld_callbacks,
22  bool always_handle_sigchild) :
23  signal_(*(evm->io_service())),
24  sig_callback_map_(sig_callback_map),
25  sigchld_callbacks_(sigchld_callbacks),
26  always_handle_sigchild_(always_handle_sigchild) {
27  Initialize();
28 }
29 
31  const SignalCallbackMap &sig_callback_map) :
32  signal_(*(evm->io_service())),
33  sig_callback_map_(sig_callback_map),
34  sigchld_callbacks_(std::vector<SignalChildHandler>()),
35  always_handle_sigchild_(false) {
36  Initialize();
37 }
38 
40 }
41 
42 boost::system::error_code Signal::AddSignal(int sig) {
43  boost::system::error_code ec;
44  signal_.add(sig, ec);
45  if (ec) {
46  std::string sigstr(strsignal(sig));
47  LOG(ERROR, sigstr << " registration failed: " << ec);
48  }
49  return ec;
50 }
51 
52 void Signal::RegisterHandler(int sig, SignalHandler handler) {
53  SignalCallbackMap::iterator it = sig_callback_map_.find(sig);
54  if (it == sig_callback_map_.end()) {
55  // Add signal first
56  AddSignal(sig);
57  sig_callback_map_.insert(std::make_pair(sig,
58  std::vector<SignalHandler>(1, handler)));
59  } else {
60  std::vector<SignalHandler> &sig_handlers(it->second);
61  sig_handlers.push_back(handler);
62  }
63 }
64 
65 void Signal::NotifySigChld(const boost::system::error_code &error, int sig,
66  int pid, int status) {
67  BOOST_FOREACH(const SignalChildHandler &sh, sigchld_callbacks_) {
68  sh(error, sig, pid, status);
69  }
70 }
71 
72 void Signal::NotifySig(const boost::system::error_code &error,
73  int sig) {
74  SignalCallbackMap::const_iterator it = sig_callback_map_.find(sig);
75  if (it == sig_callback_map_.end()) {
76  return;
77  }
78  const std::vector<SignalHandler> &callbacks(it->second);
79  BOOST_FOREACH(const SignalHandler &sh, callbacks) {
80  sh(error, sig);
81  }
82 }
83 
84 int Signal::WaitPid(int pid, int *status, int options) {
85  return ::waitpid(pid, status, options);
86 }
87 
88 void Signal::HandleSig(const boost::system::error_code &error, int sig) {
89  if (!error) {
90  if (!HandleSigOsSpecific(error, sig)) {
91  NotifySig(error, sig);
92  }
94  }
95 }
96 
98  signal_.async_wait(boost::bind(&Signal::HandleSig, this, _1, _2));
99 }
100 
102  boost::system::error_code ec;
103 
104  // Add signals
105  BOOST_FOREACH(int sig, sig_callback_map_ | boost::adaptors::map_keys) {
106  ec = AddSignal(sig);
107  }
108 
109  ec = InitializeSigChild();
110 
112 }
113 
115  boost::system::error_code ec;
116  signal_.cancel(ec);
117  signal_.clear(ec);
118 }
119 
120 } // namespace process
virtual int WaitPid(int pid, int *status, int options)
boost::system::error_code InitializeSigChild()
SignalCallbackMap sig_callback_map_
boost::function< void(const boost::system::error_code &error, int sig, pid_t pid, int status)> SignalChildHandler
void RegisterHandler(int sig, SignalHandler handler)
std::map< int, std::vector< SignalHandler > > SignalCallbackMap
std::vector< SignalChildHandler > sigchld_callbacks_
boost::function< void(const boost::system::error_code &error, int sig)> SignalHandler
bool HandleSigOsSpecific(const boost::system::error_code &error, int sig)
Signal(EventManager *evm, const SignalCallbackMap &sig_callback_map, const std::vector< SignalChildHandler > &sigchld_callbacks, bool always_handle_sigchild)
void HandleSig(const boost::system::error_code &error, int sig)
boost::asio::signal_set signal_
boost::system::error_code AddSignal(int sig)
void NotifySigChld(const boost::system::error_code &error, int sig, int pid, int status)
void NotifySig(const boost::system::error_code &error, int sig)
static EventManager evm
#define LOG(_Level, _Msg)
Definition: logging.h:34