-// Copyright (C) 2015-2020 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2015-2021 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
sigemptyset(&sset);
sigaddset(&sset, SIGCHLD);
pthread_sigmask(SIG_BLOCK, &sset, &osset);
- if (sigismember(&osset, SIGCHLD)) {
- isc_throw(ProcessSpawnError,
- "spawn() called from a thread where SIGCHLD is blocked");
- }
// Create the child
pid_t pid = fork();
} else if (pid == 0) {
// We're in the child process.
+ // Restore signal mask.
sigprocmask(SIG_SETMASK, &osset, 0);
// Run the executable.
if (execve(executable_.c_str(), args_.get(), vars_.get()) != 0) {
store_ = true;
process_collection_[this].insert(std::pair<pid_t, ProcessStatePtr>(pid, ProcessStatePtr(new ProcessState())));
} catch(...) {
+ // Restore signal mask.
pthread_sigmask(SIG_SETMASK, &osset, 0);
throw;
}
}
+ // Restore signal mask.
pthread_sigmask(SIG_SETMASK, &osset, 0);
return (pid);
}
EXPECT_THROW(thread_pool->reset(), InvalidOperation);
EXPECT_THROW(thread_pool->wait(), InvalidOperation);
EXPECT_THROW(thread_pool->wait(0), InvalidOperation);
+ sigset_t nsset;
+ pthread_sigmask(SIG_SETMASK, 0, &nsset);
+ EXPECT_EQ(1, sigismember(&nsset, SIGCHLD));
EXPECT_NO_THROW(runAndWait());
}
///
/// @param watch_type type of event that should occur
void worker(WatchedThread::WatchType watch_type) {
+ sigset_t nsset;
+ pthread_sigmask(SIG_SETMASK, 0, &nsset);
+ EXPECT_EQ(1, sigismember(&nsset, SIGCHLD));
for (passes_ = 1; passes_ < WORKER_MAX_PASSES; ++passes_) {
// Stop if we're told to do it.
-// Copyright (C) 2018-2020 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2018-2021 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
#include <queue>
#include <thread>
+#include <signal.h>
+
namespace isc {
namespace util {
/// @param thread_count specifies the number of threads to be created and
/// started
void startInternal(uint32_t thread_count) {
+ // Protect us against SIGCHLD signals
+ sigset_t sset;
+ sigset_t osset;
+ sigemptyset(&sset);
+ sigaddset(&sset, SIGCHLD);
+ pthread_sigmask(SIG_BLOCK, &sset, &osset);
queue_.enable(thread_count);
- for (uint32_t i = 0; i < thread_count; ++i) {
- threads_.push_back(boost::make_shared<std::thread>(&ThreadPool::run, this));
+ try {
+ for (uint32_t i = 0; i < thread_count; ++i) {
+ threads_.push_back(boost::make_shared<std::thread>(&ThreadPool::run, this));
+ }
+ } catch (...) {
+ // Restore signal mask.
+ pthread_sigmask(SIG_SETMASK, &osset, 0);
+ throw;
}
+ // Restore signal mask.
+ pthread_sigmask(SIG_SETMASK, &osset, 0);
}
/// @brief stop all the threads
-// Copyright (C) 2018-2020 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2018-2021 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
+
#include <util/watched_thread.h>
+#include <signal.h>
namespace isc {
namespace util {
clearReady(READY);
clearReady(TERMINATE);
setErrorInternal("no error");
- thread_.reset(new std::thread(thread_main));
+ // Protect us against SIGCHLD signals
+ sigset_t sset;
+ sigset_t osset;
+ sigemptyset(&sset);
+ sigaddset(&sset, SIGCHLD);
+ pthread_sigmask(SIG_BLOCK, &sset, &osset);
+ try {
+ thread_.reset(new std::thread(thread_main));
+ } catch (...) {
+ // Restore signal mask.
+ pthread_sigmask(SIG_SETMASK, &osset, 0);
+ throw;
+ }
+ // Restore signal mask.
+ pthread_sigmask(SIG_SETMASK, &osset, 0);
}
int