13 #include <sys/types.h> 18 #if defined(__APPLE__) 19 #include <sys/sysctl.h> 48 return !(::kill(_PID, 0) == -1 && errno == ESRCH);
58 CPIDFile(
const std::string& _FileName, pid_t _PID)
59 : m_FileName(_FileName)
61 if (!_FileName.empty() && _PID > 0)
69 throw std::runtime_error(
"Error creating pidfile. The process corresponding to pidfile \"" +
70 _FileName +
"\" is still running");
74 std::ofstream f(m_FileName.c_str());
76 throw std::runtime_error(
"can't create PID file: " + m_FileName);
86 if (!m_FileName.empty())
87 ::unlink(m_FileName.c_str());
92 std::ifstream f(_FileName.c_str());
103 std::string m_FileName;
106 #if defined(__APPLE__) 117 typedef std::set<pid_t> ProcContainer_t;
120 static void getAllPIDsForProcessName(
const std::string& _processName,
121 ProcContainer_t* _pidContainer,
122 bool _filterForRealUserID =
false)
128 int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
132 struct kinfo_proc* BSDProcInfo = NULL;
134 if (_processName.empty())
139 _pidContainer->clear();
145 error = sysctl(mib, 3, NULL, &buffSize, NULL, 0);
147 throw system_error(
"Error occurred while retrieving a running processes list");
149 BSDProcInfo = (
struct kinfo_proc*)malloc(buffSize);
151 if (BSDProcInfo == NULL)
153 "Error occurred while retrieving a running processes list. Unable to allocate the buffer.");
155 error = sysctl(mib, 3, BSDProcInfo, &buffSize, NULL, 0);
177 uid_t userid = getuid();
179 const size_t processCount = buffSize /
sizeof(
struct kinfo_proc);
180 for (
size_t i = 0; i < processCount; ++i)
183 const pid_t pid = BSDProcInfo[i].kp_proc.p_pid;
185 const std::string name = BSDProcInfo[i].kp_proc.p_comm;
187 const uid_t uid = BSDProcInfo[i].kp_eproc.e_pcred.p_ruid;
189 if ((pid > 0) && (name == _processName))
191 if (!_filterForRealUserID)
192 _pidContainer->insert(pid);
193 else if (uid == userid)
194 _pidContainer->insert(pid);
201 static bool pidExists(
int _pid)
203 int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
205 if (sysctl(name, 4, NULL, &length, NULL, 0))
206 throw system_error(
"Unable to call sysctl in the pidExists function.");
207 kinfo_proc* result = (kinfo_proc*)malloc(length);
208 if (sysctl(name, 4, result, &length, NULL, 0))
209 throw system_error(
"Unable to call sysctl in the pidExists function.");
210 int i, procCount = length /
sizeof(kinfo_proc);
211 for (i = 0; i < procCount; ++i)
213 kinfo_proc* test = &result[i];
215 if (test->kp_proc.p_pid == _pid)
240 #if !defined(__APPLE__) 250 throw std::invalid_argument(
"CProcList::GetProcList: Input container is NULL");
254 struct dirent** namelist;
256 int n = scandir(
"/proc", &namelist, CheckDigit, alphasort);
263 for (
int i = 0; i < n; ++i)
265 std::stringstream ss(namelist[i]->d_name);
276 static int CheckDigit(
const struct dirent* _d)
278 const std::string sName(_d->d_name);
280 return (sName.end() == std::find_if(sName.begin(), sName.end(), std::not1(
IsDigit())));
285 #if !defined(__APPLE__) 304 typedef std::auto_ptr<std::ifstream> ifstream_ptr;
305 typedef std::map<std::string, std::string> keyvalue_t;
311 regcomp(&m_re,
"(.*):(.*)", REG_EXTENDED);
323 std::stringstream ss;
324 ss <<
"/proc/" << _PId <<
"/status";
325 m_f = ifstream_ptr(
new std::ifstream(ss.str().c_str()));
345 std::string
GetValue(
const std::string& _KeyName)
const 348 std::string sKey(_KeyName);
351 keyvalue_t::const_iterator iter = m_values.find(sKey);
352 return (m_values.end() == iter ? std::string() : iter->second);
356 bool _Parser(
const std::string& _sVal)
358 regmatch_t PMatch[3];
359 if (0 != regexec(&m_re, _sVal.c_str(), 3, PMatch, 0))
361 std::string sKey(_sVal.c_str() + PMatch[1].rm_so, PMatch[1].rm_eo - PMatch[1].rm_so);
362 std::string sValue(_sVal.c_str() + PMatch[2].rm_so, PMatch[2].rm_eo - PMatch[2].rm_so);
366 trim<std::string>(&sValue,
'\t');
367 trim<std::string>(&sValue,
' ');
369 m_values.insert(keyvalue_t::value_type(sKey, sValue));
383 #if !defined(__APPLE__) 384 struct SFindName :
public std::binary_function<CProcList::ProcContainer_t::value_type, std::string, bool>
386 bool operator()(CProcList::ProcContainer_t::value_type _pid,
const std::string& _Name)
const 390 return (p.
GetValue(
"Name") == _Name);
400 inline vectorPid_t
getprocbyname(
const std::string& _Srv,
bool _filterForRealUserID =
false)
403 #if defined(__APPLE__) 404 CFindProcess::ProcContainer_t container;
405 CFindProcess::getAllPIDsForProcessName(_Srv, &container, _filterForRealUserID);
406 copy(container.begin(), container.end(), std::back_inserter(retVal));
411 CProcList::ProcContainer_t::const_iterator iter = pids.begin();
414 iter = std::find_if(iter, pids.end(), std::bind2nd(
SFindName(), _Srv));
415 if (pids.end() == iter)
418 retVal.push_back(*iter);
427 return WIFEXITED(status) && WEXITSTATUS(status) == 0;
431 std::string _stdoutFileName,
432 std::string _stderrFileName)
436 switch (wordexp(_Command.c_str(), &result, 0))
450 stat(result.we_wordv[0], &info);
451 if (!(info.st_mode & S_IXUSR))
453 int ret = chmod(result.we_wordv[0], info.st_mode | S_IXUSR);
455 throw system_error(
"Can't set executable flag on " + std::string(result.we_wordv[0]));
459 switch (child_pid = fork())
463 throw std::runtime_error(
"do_execv: Unable to fork process");
467 int fd_out = open(_stdoutFileName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
470 int fd_err = open(_stderrFileName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
482 execv(result.we_wordv[0], result.we_wordv);
494 inline void do_execv(
const std::string& _Command)
throw(std::exception)
498 switch (wordexp(_Command.c_str(), &result, 0))
512 stat(result.we_wordv[0], &info);
513 if (!(info.st_mode & S_IXUSR))
515 int ret = chmod(result.we_wordv[0], info.st_mode | S_IXUSR);
517 throw system_error(
"Can't set executable flag on " + std::string(result.we_wordv[0]));
527 ::waitpid(pid1, &status, WUNTRACED);
540 execv(result.we_wordv[0], result.we_wordv);
547 throw std::runtime_error(
"do_execv: Unable to fork process");
553 throw std::runtime_error(
"do_execv: Unable to fork process");
562 std::string* _output,
563 std::string* _errout =
nullptr,
564 int* _exitCode =
nullptr) throw(
std::exception)
571 if (pipe(fdpipe_out))
576 if (pipe(fdpipe_err))
582 switch (wordexp(_Command.c_str(), &result, 0))
596 stat(result.we_wordv[0], &info);
597 if (!(info.st_mode & S_IXUSR))
599 int ret = chmod(result.we_wordv[0], info.st_mode | S_IXUSR);
601 throw system_error(
"Can't set executable flag on " + std::string(result.we_wordv[0]));
603 switch (child_pid = fork())
608 close(fdpipe_out[0]);
609 close(fdpipe_out[1]);
613 close(fdpipe_err[0]);
614 close(fdpipe_err[1]);
617 throw std::runtime_error(
"do_execv: Unable to fork process");
622 close(fdpipe_out[0]);
623 dup2(fdpipe_out[1], STDOUT_FILENO);
624 close(fdpipe_out[1]);
628 close(fdpipe_err[0]);
629 dup2(fdpipe_err[1], STDERR_FILENO);
630 close(fdpipe_err[1]);
634 execv(result.we_wordv[0], result.we_wordv);
649 close(fdpipe_out[1]);
651 std::stringstream ss;
652 while (read(fdpipe_out[0], &buf, 1) > 0)
659 close(fdpipe_err[1]);
661 std::stringstream ss;
662 while (read(fdpipe_err[0], &buf, 1) > 0)
668 for (
size_t i = 0; i < _Delay; ++i)
671 if (child_pid == ::waitpid(child_pid, &stat, WNOHANG))
674 if (_exitCode !=
nullptr)
676 *_exitCode = WEXITSTATUS(stat);
680 std::stringstream ss;
682 if (WIFSIGNALED(stat))
683 ss <<
"Child ended because of an uncaught signal.";
684 else if (WIFSTOPPED(stat))
685 ss <<
"Child process has stopped.";
687 ss <<
" (exit code: " << WEXITSTATUS(stat) <<
"). Process: \"" << _Command <<
"\"";
688 throw std::runtime_error(ss.str());
695 throw std::runtime_error(
"do_execv: Timeout has been reached, command execution will be terminated.");
697 kill(child_pid, SIGKILL);
std::vector< std::string > StringVector_t
An STL vector of strings.
Definition: def.h:115
This class is used to quarry a list of currently running processes.
Definition: Process.h:241
~CPIDFile()
Definition: Process.h:84
std::vector< pid_t > vectorPid_t
Definition: Process.h:398
The system_error exception class retrieves a string, which represent the last error.
Definition: ErrorCode.h:77
_T & to_lower(_T &_str)
convert string to lower case.
Definition: MiscUtils.h:245
void Open(pid_t _PId)
Definition: Process.h:317
A PID-file helper.
Definition: Process.h:55
mem_fun1_t< _Result, _Class, _Argument > mem_fun(_Result(_Class::*member)(_Argument))
The mem_fun() template is a custom mem_fun adapter, which extends std::mem_fun.
Definition: stlx.h:55
CProcStatus()
Definition: Process.h:308
CPIDFile(const std::string &_FileName, pid_t _PID)
Definition: Process.h:58
bool operator()(CProcList::ProcContainer_t::value_type _pid, const std::string &_Name) const
Definition: Process.h:386
pid_t do_execv_std2file(const std::string &_Command, std::string _stdoutFileName, std::string _stderrFileName)
Definition: Process.h:430
static void GetProcList(ProcContainer_t *_Procs)
Definition: Process.h:247
static pid_t GetPIDFromFile(const std::string &_FileName)
Definition: Process.h:90
~CProcStatus()
Definition: Process.h:313
This custom istream iterator helps to read input line by line without breaking lines after whitespace...
Definition: CustomIterator.h:24
vectorPid_t getprocbyname(const std::string &_Srv, bool _filterForRealUserID=false)
Definition: Process.h:400
std::set< pid_t > ProcContainer_t
Definition: Process.h:244
Definition: Process.h:384
Definition: MiscUtils.h:215
std::string GetValue(const std::string &_KeyName) const
Definition: Process.h:345
bool IsProcessExist(pid_t _PID)
The function checks, whether the process which corresponds to the given _PID can be found...
Definition: Process.h:46
void do_execv(const std::string &_Command)
We do not want the parent process to wait for its child process and we do not want to create a zombie...
Definition: Process.h:494
bool is_status_ok(int status)
Definition: Process.h:425
Miscellaneous functions and helpers are located here.
Definition: BOOST_FILESYSTEM.h:21
This class helps to retrieve process's information from /proc/<pid>/status.
Definition: Process.h:302