25#include <boost/make_shared.hpp> 
   28namespace ph = std::placeholders;
 
   56class processSpawnImpl;
 
   87                     const std::string& executable,
 
   90                     const bool inherit_env);
 
  112    pid_t 
spawn(
bool dismiss);
 
  151    class IOSignalSetInitializer {
 
  157        IOSignalSetInitializer(
IOServicePtr io_service) : io_service_(io_service) {
 
  162                boost::make_shared<IOSignalSet>(io_service,
 
  163                                                std::bind(&ProcessSpawnImpl::waitForProcess, ph::_1,
 
  165            io_signal_set_->add(SIGCHLD);
 
  169        ~IOSignalSetInitializer() {
 
  170            io_signal_set_->remove(SIGCHLD);
 
  171            io_signal_set_.reset();
 
  172            io_service_->stopAndPoll();
 
  206    char* allocateInternal(
const std::string& src);
 
  216    static void waitForProcess(
int signum, pid_t 
const wpid = -1,
 
  217                               bool const sync = 
false);
 
  227    std::string executable_;
 
  230    boost::shared_ptr<char*[]> args_;
 
  233    boost::shared_ptr<char*[]> vars_;
 
  236    typedef boost::shared_ptr<char[]> CStringPtr;
 
  239    std::vector<CStringPtr> storage_;
 
  245    static std::mutex mutex_;
 
 
  249std::mutex ProcessSpawnImpl::mutex_;
 
  251void ProcessSpawnImpl::IOSignalSetInitializer::initIOSignalSet(
IOServicePtr io_service) {
 
  252    static IOSignalSetInitializer init(io_service);
 
  256                                   const std::string& executable,
 
  259                                   const bool inherit_env)
 
  260    : mode_(mode), executable_(executable), args_(new char*[args.size() + 2]),
 
  270        vars_size = i + vars.size();
 
  272        vars_size = vars.size();
 
  275    vars_ = boost::shared_ptr<char*[]>(
new char*[vars_size + 1]);
 
  279    if (stat(executable_.c_str(), &st)) {
 
  283    if (!(st.st_mode & S_IEXEC)) {
 
  290    memset(args_.get(), 0, (args.size() + 2) * 
sizeof(
char*));
 
  291    memset(vars_.get(), 0, (vars_size + 1) * 
sizeof(
char*));
 
  293    args_[0] = allocateInternal(executable_);
 
  295    for (
size_t i = 1; i <= args.size(); ++i) {
 
  296        args_[i] = allocateInternal(args[i - 1]);
 
  302            vars_[i] = allocateInternal(
environ[i]);
 
  306    for (
size_t j = 0; j < vars.size(); ++j) {
 
  307        vars_[i + j] = allocateInternal(vars[j]);
 
 
  313        lock_guard<std::mutex> lk(mutex_);
 
  314        process_collection_.erase(
this);
 
 
  320    std::ostringstream s;
 
  326    while (args_[i] != NULL) {
 
  327        s << 
" " << args_[i];
 
 
  335    lock_guard<std::mutex> lk(mutex_);
 
  344    } 
else if (pid == 0) {
 
  348        pthread_sigmask(SIG_SETMASK, &sset, 0);
 
  350        execve(executable_.c_str(), args_.get(), vars_.get());
 
  363        waitForProcess(SIGCHLD, pid,  
true);
 
 
  371    lock_guard<std::mutex> lk(mutex_);
 
  372    ProcessStates::const_iterator proc;
 
  373    if (process_collection_.find(
this) == process_collection_.end() ||
 
  374        (proc = process_collection_[
this].find(pid)) == process_collection_[
this].end()) {
 
  377    return (proc->second->running_);
 
 
  382    lock_guard<std::mutex> lk(mutex_);
 
  383    if (process_collection_.find(
this) != process_collection_.end()) {
 
  384        for (
auto const& proc : process_collection_[
this]) {
 
  385            if (proc.second->running_) {
 
 
  395    lock_guard<std::mutex> lk(mutex_);
 
  396    ProcessStates::const_iterator proc;
 
  397    if (process_collection_.find(
this) == process_collection_.end() ||
 
  398        (proc = process_collection_[
this].find(pid)) == process_collection_[
this].end()) {
 
  401    return (WEXITSTATUS(proc->second->status_));
 
 
  405ProcessSpawnImpl::allocateInternal(
const std::string& src) {
 
  406    const size_t src_len = src.length();
 
  407    storage_.push_back(CStringPtr(
new char[src_len + 1]));
 
  409    char* dest = storage_[storage_.size() - 1].get();
 
  411    src.copy(dest, src_len);
 
  413    dest[src_len] = 
'\0';
 
  418ProcessSpawnImpl::waitForProcess(
int ,
 
  423    unique_lock<std::mutex> lk{mutex_, std::defer_lock};
 
  433        pid_t pid = waitpid(wpid, &status, sync ? 0 : WNOHANG);
 
  438            if (errno == EINTR) {
 
  444            isc_throw(InvalidOperation, 
"process with pid " << wpid << 
" has returned " << pid
 
  445                                                            << 
" from waitpid in sync mode, errno: " 
  447        } 
else if (pid == 0) {
 
  452            for (
auto const& instance : process_collection_) {
 
  453                auto const& proc = instance.second.find(pid);
 
  456                if (proc != instance.second.end()) {
 
  457                    proc->second->status_ = status;
 
  458                    proc->second->running_ = 
false;
 
  473                  "process (pid: " << pid << 
") which is still running");
 
  475    lock_guard<std::mutex> lk(mutex_);
 
  476    if (process_collection_.find(
this) != process_collection_.end()) {
 
  477        process_collection_[
this].erase(pid);
 
 
  484                           const std::string& executable,
 
  487                           const bool inherit_env )
 
 
  493    return (impl_->getCommandLine());
 
 
  498    return (impl_->spawn(dismiss));
 
 
  503    return (impl_->isRunning(pid));
 
 
  508    return (impl_->isAnyRunning());
 
 
  513    return (impl_->getExitStatus(pid));
 
 
  518    return (impl_->clearState(pid));
 
 
A generic exception that is thrown if a function is called in a prohibited way.
Exception thrown when error occurs during spawning a process.
Implementation of the ProcessSpawn class.
void clearState(const pid_t pid)
Removes the status of the process with a specified PID.
bool isAnyRunning() const
Checks if any of the spawned processes is still running.
std::string getCommandLine() const
Returns full command line, including arguments, for the process.
ProcessSpawnImpl(const ProcessSpawn::SpawnMode mode, const std::string &executable, const ProcessArgs &args, const ProcessEnvVars &vars, const bool inherit_env)
Constructor.
pid_t spawn(bool dismiss)
Spawn the new process.
~ProcessSpawnImpl()
Destructor.
bool isRunning(const pid_t pid) const
Checks if the process is still running.
int getExitStatus(const pid_t pid) const
Returns exit status of the process.
bool isAnyRunning() const
Checks if any of the spawned processes is still running.
int getExitStatus(const pid_t pid) const
Returns exit status of the process.
void clearState(const pid_t pid)
Removes the status of the process with a specified PID.
ProcessSpawn(const SpawnMode mode, const std::string &executable, const ProcessArgs &args=ProcessArgs(), const ProcessEnvVars &vars=ProcessEnvVars(), const bool inherit_env=false)
Constructor.
bool isRunning(const pid_t pid) const
Checks if the process is still running.
std::string getCommandLine() const
Returns full command line, including arguments, for the process.
pid_t spawn(bool dismiss=false)
Spawn the new process.
static isc::asiolink::IOServicePtr getIOService()
Get the I/O service.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
std::map< const ProcessSpawnImpl *, ProcessStates > ProcessCollection
ProcessCollection container which stores all ProcessStates for each instance of ProcessSpawnImpl.
std::vector< std::string > ProcessArgs
Type of the container holding arguments of the executable being run as a background process.
boost::shared_ptr< ProcessState > ProcessStatePtr
Defines a pointer to a ProcessState.
std::vector< std::string > ProcessEnvVars
Type of the container holding environment variables of the executable being run as a background proce...
std::map< pid_t, ProcessStatePtr > ProcessStates
ProcessStates container which stores a ProcessState for each process identified by PID.
boost::shared_ptr< IOService > IOServicePtr
Defines a smart pointer to an IOService instance.
boost::shared_ptr< IOSignalSet > IOSignalSetPtr
Defines a pointer to an IOSignalSet.
Defines the logger used by the top-level component of kea-lfc.
bool running_
true until the exit status is collected
ProcessState()
Constructor.
int status_
0 or the exit status