]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#899] clear signal handle after process has finished
authorRazvan Becheriu <razvan@isc.org>
Wed, 17 Feb 2021 19:50:10 +0000 (21:50 +0200)
committerRazvan Becheriu <razvan@isc.org>
Thu, 18 Feb 2021 17:23:57 +0000 (19:23 +0200)
src/hooks/dhcp/run_script/run_script.cc
src/hooks/dhcp/run_script/run_script.h
src/lib/asiolink/io_service_signal.cc
src/lib/asiolink/io_service_signal.h
src/lib/asiolink/process_spawn.cc
src/lib/asiolink/process_spawn.h
src/lib/util/util.dox

index 1a177c4c3e3cb5941aaefda4d371462c70346616..a7748e95d86d7e06e50a12aaca818725221e4921 100644 (file)
@@ -45,7 +45,7 @@ RunScriptImpl::configure(LibraryHandle& handle) {
 void
 RunScriptImpl::runScript(const ProcessArgs& args, const ProcessEnvVars& vars) {
     ProcessSpawn process(io_service_, name_, args, vars);
-    process.spawn();
+    process.spawn(true);
 }
 
 void
index d12612d037fd47dec4158eb1964acc8f2da53899..4fd370c7b1cd7b555d34b67de7e409b68fbc55f6 100644 (file)
@@ -195,7 +195,7 @@ public:
     /// @brief Get name of the target script.
     ///
     /// @return The name of the target script.
-    std::string getName() {
+    std::string getName() const {
         return (name_);
     }
 
@@ -209,7 +209,7 @@ public:
     /// @brief Get the synchronous call mode for the target script.
     ///
     /// @return The synchronous call mode for the target script.
-    bool getSync() {
+    bool getSync() const {
         return (sync_);
     }
 
index 44c7658a14c243882ac496b1aa748d10a11f766e..d75fac67c503a097d856f5c96afaa6b14412b1f6 100644 (file)
@@ -20,9 +20,8 @@ namespace isc {
 namespace asiolink {
 
 /// @brief Implementation class of IOSignalSet.
-class IOSignalSetImpl :
-    public boost::enable_shared_from_this<IOSignalSetImpl>,
-    public boost::noncopyable {
+class IOSignalSetImpl : public boost::enable_shared_from_this<IOSignalSetImpl>,
+                        public boost::noncopyable {
 public:
     /// @brief Constructor.
     ///
@@ -31,16 +30,21 @@ public:
     IOSignalSetImpl(IOServicePtr io_service, IOSignalHandler handler);
 
     /// @brief Destructor.
-    ~IOSignalSetImpl(){}
+    ~IOSignalSetImpl() = default;
 
     /// @brief Install the callback on the IO service queue.
     void install();
 
-    /// @brief Add a signal in the ASIO signal set.
+    /// @brief Add a signal to the ASIO signal set.
     ///
     /// @param signum the signal number.
     void add(int signum);
 
+    /// @brief Remove a signal from the ASIO signal set.
+    ///
+    /// @param signum the signal number.
+    void remove(int signum);
+
 private:
     /// @brief the ASIO signal set.
     boost::asio::signal_set signal_set_;
@@ -85,8 +89,18 @@ IOSignalSetImpl::add(int signum) {
     try {
         signal_set_.add(signum);
     } catch (const boost::system::system_error& ex) {
-        isc_throw(isc::Unexpected, "Failed to add signal " << signum
-                  << ": " << ex.what());
+        isc_throw(isc::Unexpected,
+                  "Failed to add signal " << signum << ": " << ex.what());
+    }
+}
+
+void
+IOSignalSetImpl::remove(int signum) {
+    try {
+        signal_set_.remove(signum);
+    } catch (const boost::system::system_error& ex) {
+        isc_throw(isc::Unexpected,
+                  "Failed to add signal " << signum << ": " << ex.what());
     }
 }
 
@@ -96,14 +110,15 @@ IOSignalSet::IOSignalSet(IOServicePtr io_service, IOSignalHandler handler) :
     impl_->install();
 }
 
-IOSignalSet::~IOSignalSet() {
-    impl_.reset();
-}
-
 void
 IOSignalSet::add(int signum) {
     impl_->add(signum);
 }
 
+void
+IOSignalSet::remove(int signum) {
+    impl_->remove(signum);
+}
+
 } // namespace asiolink
 } // namespace isc
index 7efabf96465630b6aecaa474a9c4e828d19a784c..5032e8e526046eba11ec590d5395355c455ac87e 100644 (file)
@@ -32,7 +32,7 @@ public:
     IOSignalSet(asiolink::IOServicePtr io_service, IOSignalHandler handler);
 
     /// @brief Destructor.
-    ~IOSignalSet();
+    ~IOSignalSet() = default;
 
     /// @brief Add a signal to the list of signals to handle.
     ///
@@ -40,6 +40,12 @@ public:
     /// @throw Unexpected on error.
     void add(int signum);
 
+    /// @brief Remove a signal from the list of signals to handle.
+    ///
+    /// @param signum Signal number.
+    /// @throw Unexpected on error.
+    void remove(int signum);
+
 private:
     /// @brief Pointer to the implementation.
     boost::shared_ptr<IOSignalSetImpl> impl_;
index 05854c885cc06376d50ad39672a06c6a7ea26db7..2090424329e07ffcdc0e87de1ce9f5a6ca65f768 100644 (file)
@@ -86,9 +86,11 @@ public:
     /// or when the executable does not exist. If the process ends successfully
     /// the EXIT_SUCCESS is returned.
     ///
+    /// @param dismiss The flag which indicated if the process status can be
+    /// disregarded.
     /// @return PID of the spawned process.
     /// @throw ProcessSpawnError if forking a current process failed.
-    pid_t spawn();
+    pid_t spawn(bool dismiss);
 
     /// @brief Checks if the process is still running.
     ///
@@ -146,9 +148,6 @@ private:
     /// was a different signal.
     bool waitForProcess(int signum);
 
-    /// @brief ASIO signal set.
-    IOSignalSetPtr io_signal_set_;
-
     /// @brief A map holding the status codes of executed processes.
     ProcessStates process_state_;
 
@@ -169,6 +168,9 @@ private:
 
     /// @brief Mutex to protect internal state.
     boost::shared_ptr<std::mutex> mutex_;
+
+    /// @brief ASIO signal set.
+    IOSignalSetPtr io_signal_set_;
 };
 
 ProcessSpawnImpl::ProcessSpawnImpl(IOServicePtr io_service,
@@ -176,10 +178,10 @@ ProcessSpawnImpl::ProcessSpawnImpl(IOServicePtr io_service,
                                    const ProcessArgs& args,
                                    const ProcessEnvVars& vars)
     : executable_(executable), args_(new char*[args.size() + 2]),
-      vars_(new char*[vars.size() + 1]), mutex_(new std::mutex) {
-    io_signal_set_.reset(new IOSignalSet(io_service,
-                                         std::bind(&ProcessSpawnImpl::waitForProcess,
-                                                   this, ph::_1)));
+      vars_(new char*[vars.size() + 1]), mutex_(new std::mutex),
+      io_signal_set_(new IOSignalSet(io_service,
+                                     std::bind(&ProcessSpawnImpl::waitForProcess,
+                                               this, ph::_1))) {
     io_signal_set_->add(SIGCHLD);
 
     // Conversion of the arguments to the C-style array we start by setting
@@ -200,6 +202,7 @@ ProcessSpawnImpl::ProcessSpawnImpl(IOServicePtr io_service,
 }
 
 ProcessSpawnImpl::~ProcessSpawnImpl() {
+    io_signal_set_->remove(SIGCHLD);
 }
 
 std::string
@@ -218,7 +221,7 @@ ProcessSpawnImpl::getCommandLine() const {
 }
 
 pid_t
-ProcessSpawnImpl::spawn() {
+ProcessSpawnImpl::spawn(bool dismiss) {
     // Protect us against SIGCHLD signals
     sigset_t sset;
     sigset_t osset;
@@ -250,12 +253,14 @@ ProcessSpawnImpl::spawn() {
     }
 
     // We're in the parent process.
-    try {
-        lock_guard<std::mutex> lk(*mutex_);
-        process_state_.insert(std::pair<pid_t, ProcessState>(pid, ProcessState()));
-    } catch(...) {
-        pthread_sigmask(SIG_SETMASK, &osset, 0);
-        throw;
+    if (!dismiss) {
+        try {
+            lock_guard<std::mutex> lk(*mutex_);
+            process_state_.insert(std::pair<pid_t, ProcessState>(pid, ProcessState()));
+        } catch(...) {
+            pthread_sigmask(SIG_SETMASK, &osset, 0);
+            throw;
+        }
     }
     pthread_sigmask(SIG_SETMASK, &osset, 0);
     return (pid);
@@ -358,8 +363,8 @@ ProcessSpawn::getCommandLine() const {
 }
 
 pid_t
-ProcessSpawn::spawn() {
-    return (impl_->spawn());
+ProcessSpawn::spawn(bool dismiss) {
+    return (impl_->spawn(dismiss));
 }
 
 bool
index b0b2971d0dabda1d7d2eb0947ca703fd011d95b3..ef37174902d52bfbc9981ecdb6db8cfa3199feae 100644 (file)
@@ -87,8 +87,10 @@ public:
     /// or when the executable does not exist. If the process ends successfully
     /// the EXIT_SUCCESS is returned.
     ///
+    /// @param dismiss The flag which indicated if the process status can be
+    /// disregarded.
     /// @throw ProcessSpawnError if forking a current process failed.
-    pid_t spawn();
+    pid_t spawn(bool dismiss = false);
 
     /// @brief Checks if the process is still running.
     ///
index 8781f2f555c0704b4980d489df0c9973ca049cdf..e4ef04451a5f4bd525df9e74e6d5e253294244f6 100644 (file)
@@ -50,7 +50,7 @@ The utilities library (libkea-util) provides generic and Kea utilities:
 
  - read-write mutex (header only).
 
- - signal set: signal handling (please use @c isc::process::IOSignalSet
+ - signal set: signal handling (please use @c isc::asiolink::IOSignalSet
   instead).
 
  - staged values.