24 namespace ph = std::placeholders;
79 const std::string& executable,
87 std::string getCommandLine()
const;
103 pid_t spawn(
bool dismiss);
109 bool isRunning(
const pid_t pid)
const;
114 bool isAnyRunning()
const;
124 int getExitStatus(
const pid_t pid)
const;
133 void clearState(
const pid_t pid);
150 char* allocateInternal(
const std::string& src);
159 static bool waitForProcess(
int signum);
162 static ProcessCollection process_collection_;
165 std::string executable_;
168 boost::shared_ptr<char*[]> args_;
171 boost::shared_ptr<char*[]> vars_;
174 typedef boost::shared_ptr<char[]> CStringPtr;
177 std::vector<CStringPtr> storage_;
183 static std::mutex mutex_;
189 ProcessCollection ProcessSpawnImpl::process_collection_;
190 std::mutex ProcessSpawnImpl::mutex_;
193 const std::string& executable,
196 : executable_(executable), args_(new char*[args.size() + 2]),
197 vars_(new char*[vars.size() + 1]), store_(false),
203 if (stat(executable_.c_str(), &st)) {
207 if (!(st.st_mode & S_IEXEC)) {
211 io_signal_set_->add(SIGCHLD);
216 memset(args_.get(), 0, (args.size() + 2) *
sizeof(
char*));
217 memset(vars_.get(), 0, (vars.size() + 1) *
sizeof(
char*));
219 args_[0] = allocateInternal(executable_);
221 for (
int i = 1; i <= args.size(); ++i) {
222 args_[i] = allocateInternal(args[i - 1]);
225 for (
int i = 0; i < vars.size(); ++i) {
226 vars_[i] = allocateInternal(vars[i]);
231 io_signal_set_->remove(SIGCHLD);
233 lock_guard<std::mutex> lk(mutex_);
234 process_collection_.erase(
this);
240 std::ostringstream s;
246 while (args_[i] != NULL) {
247 s <<
" " << args_[i];
255 lock_guard<std::mutex> lk(mutex_);
261 }
else if (pid == 0) {
263 execve(executable_.c_str(), args_.get(), vars_.get());
279 lock_guard<std::mutex> lk(mutex_);
280 ProcessStates::const_iterator proc;
281 if (process_collection_.find(
this) == process_collection_.end() ||
282 (proc = process_collection_[
this].find(pid)) == process_collection_[
this].end()) {
284 <<
"' hasn't been spawned and it status cannot be"
287 return (proc->second->running_);
292 lock_guard<std::mutex> lk(mutex_);
293 if (process_collection_.find(
this) != process_collection_.end()) {
294 for (
auto const& proc : process_collection_[
this]) {
295 if (proc.second->running_) {
305 lock_guard<std::mutex> lk(mutex_);
306 ProcessStates::const_iterator proc;
307 if (process_collection_.find(
this) == process_collection_.end() ||
308 (proc = process_collection_[
this].find(pid)) == process_collection_[
this].end()) {
310 <<
"' hasn't been spawned and it status cannot be"
313 return (WEXITSTATUS(proc->second->status_));
317 ProcessSpawnImpl::allocateInternal(
const std::string& src) {
318 const size_t src_len = src.length();
319 storage_.push_back(CStringPtr(
new char[src_len + 1]));
321 char* dest = storage_[storage_.size() - 1].get();
323 src.copy(dest, src_len);
325 dest[src_len] =
'\0';
330 ProcessSpawnImpl::waitForProcess(
int) {
331 lock_guard<std::mutex> lk(mutex_);
334 pid_t pid = waitpid(-1, &status, WNOHANG);
338 for (
auto const& instance : process_collection_) {
339 auto const& proc = instance.second.find(pid);
342 if (proc != instance.second.end()) {
344 proc->second->status_ = status;
345 proc->second->running_ =
false;
356 "process (pid: " << pid <<
") which is still running");
358 lock_guard<std::mutex> lk(mutex_);
359 if (process_collection_.find(
this) != process_collection_.end()) {
360 process_collection_[
this].erase(pid);
365 const std::string& executable,
373 return (impl_->getCommandLine());
378 return (impl_->spawn(dismiss));
383 return (impl_->isRunning(pid));
388 return (impl_->isAnyRunning());
393 return (impl_->getExitStatus(pid));
398 return (impl_->clearState(pid));
bool running_
true until the exit status is collected
int getExitStatus(const pid_t pid) const
Returns exit status of the process.
ProcessSpawn(isc::asiolink::IOServicePtr io_service, const std::string &executable, const ProcessArgs &args=ProcessArgs(), const ProcessEnvVars &vars=ProcessEnvVars())
Constructor.
bool isAnyRunning() const
Checks if any of the spawned processes is still running.
bool isRunning(const pid_t pid) const
Checks if the process is still running.
pid_t spawn(bool dismiss=false)
Spawn the new process.
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.
std::string getCommandLine() const
Returns full command line, including arguments, for the process.
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.
~ProcessSpawnImpl()
Destructor.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
ProcessState()
Constructor.
Implements an asynchronous "signal" for IOService driven processing.
boost::shared_ptr< ProcessState > ProcessStatePtr
Defines a pointer to a ProcessState.
std::map< const ProcessSpawnImpl *, ProcessStates > ProcessCollection
ProcessCollection container which stores all ProcessStates for each instance of ProcessSpawnImpl.
boost::shared_ptr< IOSignalSet > IOSignalSetPtr
Defines a pointer to an IOSignalSet.
int status_
0 or the exit status
Defines the logger used by the top-level component of kea-dhcp-ddns.
Implementation of the ProcessSpawn class.
void clearState(const pid_t pid)
Removes the status of the process with a specified PID.
A wrapper interface for the ASIO library.
Exception thrown when error occurs during spawning a process.
A generic exception that is thrown if a function is called in a prohibited way.
int getExitStatus(const pid_t pid) const
Returns exit status of the process.
pid_t spawn(bool dismiss)
Spawn the new process.
std::vector< std::string > ProcessArgs
Type of the container holding arguments of the executable being run as a background process...
bool isAnyRunning() const
Checks if any of the spawned processes is still running.
void clearState(const pid_t pid)
Removes the status of the process with a specified PID.
std::vector< std::string > ProcessEnvVars
Type of the container holding environment variables of the executable being run as a background proce...