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