12 #include <boost/bind.hpp>
125 char* allocateArg(
const std::string& src)
const;
134 bool waitForProcess(
int signum);
143 std::string executable_;
151 : signals_(new
SignalSet(SIGCHLD)), process_state_(),
152 executable_(executable), args_(new char*[args.size() + 2]) {
155 signals_->setOnReceiptHandler(boost::bind(&ProcessSpawnImpl::waitForProcess,
160 memset(args_, 0, (args.size() + 2) *
sizeof(
char*));
162 args_[0] = allocateArg(executable_);
164 for (
int i = 1; i <= args.size(); ++i) {
165 args_[i] = allocateArg(args[i-1]);
172 while (args_[i] != NULL) {
182 std::ostringstream s;
188 while (args_[i] != NULL) {
189 s <<
" " << args_[i];
201 sigaddset(&sset, SIGCHLD);
202 pthread_sigmask(SIG_BLOCK, &sset, &osset);
203 if (sigismember(&osset, SIGCHLD)) {
205 "spawn() called from a thread where SIGCHLD is blocked");
213 }
else if (pid == 0) {
215 sigprocmask(SIG_SETMASK, &osset, 0);
217 if (execvp(executable_.c_str(), args_) != 0) {
228 process_state_.insert(
231 pthread_sigmask(SIG_SETMASK, &osset, 0);
234 pthread_sigmask(SIG_SETMASK, &osset, 0);
240 ProcessStates::const_iterator proc = process_state_.find(pid);
241 if (proc == process_state_.end()) {
243 <<
"' hasn't been spawned and it status cannot be"
246 return (proc->second.running_);
251 for (ProcessStates::const_iterator proc = process_state_.begin();
252 proc != process_state_.end(); ++proc) {
253 if (proc->second.running_) {
262 ProcessStates::const_iterator proc = process_state_.find(pid);
263 if (proc == process_state_.end()) {
265 <<
"' hasn't been spawned and it status cannot be"
268 return (WEXITSTATUS(proc->second.status_));
272 ProcessSpawnImpl::allocateArg(
const std::string& src)
const {
273 const size_t src_len = src.length();
275 char* dest =
new char[src_len + 1];
277 src.copy(dest, src_len);
279 dest[src_len] =
'\0';
284 ProcessSpawnImpl::waitForProcess(
int signum) {
286 if (signum != SIGCHLD) {
292 int errno_value = errno;
296 pid_t pid = waitpid(-1, &status, WNOHANG);
300 ProcessStates::iterator proc = process_state_.find(pid);
303 if (proc != process_state_.end()) {
305 proc->second.status_ = status;
306 proc->second.running_ =
false;
326 "process (pid: " << pid <<
") which is still running");
328 process_state_.erase(pid);
347 return (impl_->
spawn());