From: Razvan Becheriu Date: Tue, 8 Jun 2021 08:51:13 +0000 (+0300) Subject: [#1878] initialize SIGCHLD signal handler only once X-Git-Tag: Kea-1.9.9~83 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ef6f0a4ddf72e40128bef0d39f42c2f5d49a7bd3;p=thirdparty%2Fkea.git [#1878] initialize SIGCHLD signal handler only once --- diff --git a/src/lib/asiolink/process_spawn.cc b/src/lib/asiolink/process_spawn.cc index 93bb7571b6..5fc699b976 100644 --- a/src/lib/asiolink/process_spawn.cc +++ b/src/lib/asiolink/process_spawn.cc @@ -134,6 +134,34 @@ public: private: + /// @brief Initializer class for the SIGCHLD signal handler. + class IOSignalSetInitializer { + public: + + /// @brief Constructor + /// + /// @param io_service The IOService which handles signal handlers. + IOSignalSetInitializer(IOServicePtr io_service) : + io_signal_set_(new IOSignalSet(io_service, + std::bind(&ProcessSpawnImpl::waitForProcess, ph::_1))) { + io_signal_set_->add(SIGCHLD); + } + + /// @brief Destructor + ~IOSignalSetInitializer() { + io_signal_set_->remove(SIGCHLD); + } + + private: + /// @brief ASIO signal set. + IOSignalSetPtr io_signal_set_; + }; + + /// @brief Initialize the SIGCHLD signal handler. + /// + /// @param io_service The IOService which handles signal handlers. + static void initIOSignalSet(IOServicePtr io_service); + /// @brief Copies the argument specified as a C++ string to the new /// C string. /// @@ -182,22 +210,24 @@ private: /// @brief Mutex to protect internal state. static std::mutex mutex_; - /// @brief ASIO signal set. - IOSignalSetPtr io_signal_set_; + /// @brief The IOService which handles IO operations. + IOServicePtr io_service_; }; ProcessCollection ProcessSpawnImpl::process_collection_; std::mutex ProcessSpawnImpl::mutex_; +void ProcessSpawnImpl::initIOSignalSet(IOServicePtr io_service) { + static IOSignalSetInitializer init(io_service); +} + ProcessSpawnImpl::ProcessSpawnImpl(IOServicePtr io_service, const std::string& executable, const ProcessArgs& args, const ProcessEnvVars& vars) : executable_(executable), args_(new char*[args.size() + 2]), - vars_(new char*[vars.size() + 1]), store_(false), - io_signal_set_(new IOSignalSet(io_service, - std::bind(&ProcessSpawnImpl::waitForProcess, - ph::_1))) { + vars_(new char*[vars.size() + 1]), store_(false), io_service_(io_service) { + struct stat st; if (stat(executable_.c_str(), &st)) { @@ -208,8 +238,6 @@ ProcessSpawnImpl::ProcessSpawnImpl(IOServicePtr io_service, isc_throw(ProcessSpawnError, "File not executable: " << executable_); } - io_signal_set_->add(SIGCHLD); - // Conversion of the arguments to the C-style array we start by setting // all pointers within an array to NULL to indicate that they haven't // been allocated yet. @@ -228,7 +256,6 @@ ProcessSpawnImpl::ProcessSpawnImpl(IOServicePtr io_service, } ProcessSpawnImpl::~ProcessSpawnImpl() { - io_signal_set_->remove(SIGCHLD); if (store_) { lock_guard lk(mutex_); process_collection_.erase(this); @@ -253,6 +280,7 @@ ProcessSpawnImpl::getCommandLine() const { pid_t ProcessSpawnImpl::spawn(bool dismiss) { lock_guard lk(mutex_); + initIOSignalSet(io_service_); // Create the child pid_t pid = fork(); if (pid < 0) {