13 #include <sys/types.h> 18 #if defined(__APPLE__) 19 #include <sys/sysctl.h> 37 #include <boost/asio.hpp> 38 #pragma clang diagnostic push 39 #pragma clang diagnostic ignored "-Wunused-variable" 40 #include <boost/process.hpp> 41 #pragma clang diagnostic pop 43 namespace bp = boost::process;
58 return !(::kill(_PID, 0) == -1 && errno == ESRCH);
68 CPIDFile(
const std::string& _FileName, pid_t _PID)
69 : m_FileName(_FileName)
71 if (!_FileName.empty() && _PID > 0)
79 throw std::runtime_error(
"Error creating pidfile. The process corresponding to pidfile \"" +
80 _FileName +
"\" is still running");
84 std::ofstream f(m_FileName.c_str());
86 throw std::runtime_error(
"can't create PID file: " + m_FileName);
96 if (!m_FileName.empty())
97 ::unlink(m_FileName.c_str());
102 std::ifstream f(_FileName.c_str());
113 std::string m_FileName;
116 #if defined(__APPLE__) 127 typedef std::set<pid_t> ProcContainer_t;
130 static void getAllPIDsForProcessName(
const std::string& _processName,
131 ProcContainer_t* _pidContainer,
132 bool _filterForRealUserID =
false)
138 int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
142 struct kinfo_proc* BSDProcInfo = NULL;
144 if (_processName.empty())
149 _pidContainer->clear();
155 error = sysctl(mib, 3, NULL, &buffSize, NULL, 0);
157 throw system_error(
"Error occurred while retrieving a running processes list");
159 BSDProcInfo = (
struct kinfo_proc*)malloc(buffSize);
161 if (BSDProcInfo == NULL)
163 "Error occurred while retrieving a running processes list. Unable to allocate the buffer.");
165 error = sysctl(mib, 3, BSDProcInfo, &buffSize, NULL, 0);
187 uid_t userid = getuid();
189 const size_t processCount = buffSize /
sizeof(
struct kinfo_proc);
190 for (
size_t i = 0; i < processCount; ++i)
193 const pid_t pid = BSDProcInfo[i].kp_proc.p_pid;
195 const std::string name = BSDProcInfo[i].kp_proc.p_comm;
197 const uid_t uid = BSDProcInfo[i].kp_eproc.e_pcred.p_ruid;
199 if ((pid > 0) && (name == _processName))
201 if (!_filterForRealUserID)
202 _pidContainer->insert(pid);
203 else if (uid == userid)
204 _pidContainer->insert(pid);
211 static bool pidExists(
int _pid)
213 int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
215 if (sysctl(name, 4, NULL, &length, NULL, 0))
216 throw system_error(
"Unable to call sysctl in the pidExists function.");
217 kinfo_proc* result = (kinfo_proc*)malloc(length);
218 if (sysctl(name, 4, result, &length, NULL, 0))
219 throw system_error(
"Unable to call sysctl in the pidExists function.");
220 int i, procCount = length /
sizeof(kinfo_proc);
221 for (i = 0; i < procCount; ++i)
223 kinfo_proc* test = &result[i];
225 if (test->kp_proc.p_pid == _pid)
250 #if !defined(__APPLE__) 260 throw std::invalid_argument(
"CProcList::GetProcList: Input container is NULL");
264 struct dirent** namelist;
266 int n = scandir(
"/proc", &namelist, CheckDigit, alphasort);
273 for (
int i = 0; i < n; ++i)
275 std::stringstream ss(namelist[i]->d_name);
286 static int CheckDigit(
const struct dirent* _d)
288 const std::string sName(_d->d_name);
290 return (sName.end() == std::find_if(sName.begin(), sName.end(), std::not1(
IsDigit())));
295 #if !defined(__APPLE__) 314 typedef std::shared_ptr<std::ifstream> ifstream_ptr;
315 typedef std::map<std::string, std::string> keyvalue_t;
321 regcomp(&m_re,
"(.*):(.*)", REG_EXTENDED);
333 std::stringstream ss;
334 ss <<
"/proc/" << _PId <<
"/status";
335 m_f = ifstream_ptr(
new std::ifstream(ss.str().c_str()));
355 std::string
GetValue(
const std::string& _KeyName)
const 358 std::string sKey(_KeyName);
361 keyvalue_t::const_iterator iter = m_values.find(sKey);
362 return (m_values.end() == iter ? std::string() : iter->second);
366 bool _Parser(
const std::string& _sVal)
368 regmatch_t PMatch[3];
369 if (0 != regexec(&m_re, _sVal.c_str(), 3, PMatch, 0))
371 std::string sKey(_sVal.c_str() + PMatch[1].rm_so, PMatch[1].rm_eo - PMatch[1].rm_so);
372 std::string sValue(_sVal.c_str() + PMatch[2].rm_so, PMatch[2].rm_eo - PMatch[2].rm_so);
376 trim<std::string>(&sValue,
'\t');
377 trim<std::string>(&sValue,
' ');
379 m_values.insert(keyvalue_t::value_type(sKey, sValue));
393 #if !defined(__APPLE__) 394 struct SFindName :
public std::binary_function<CProcList::ProcContainer_t::value_type, std::string, bool>
396 bool operator()(CProcList::ProcContainer_t::value_type _pid,
const std::string& _Name)
const 400 return (p.
GetValue(
"Name") == _Name);
410 inline vectorPid_t
getprocbyname(
const std::string& _Srv,
bool _filterForRealUserID =
false)
413 #if defined(__APPLE__) 414 CFindProcess::ProcContainer_t container;
415 CFindProcess::getAllPIDsForProcessName(_Srv, &container, _filterForRealUserID);
416 copy(container.begin(), container.end(), std::back_inserter(retVal));
421 CProcList::ProcContainer_t::const_iterator iter = pids.begin();
424 iter = std::find_if(iter, pids.end(), std::bind2nd(
SFindName(), _Srv));
425 if (pids.end() == iter)
428 retVal.push_back(*iter);
441 return WIFEXITED(status) && WEXITSTATUS(status) == 0;
448 inline pid_t
execute(
const std::string& _Command,
449 const std::string& _stdoutFileName,
450 const std::string& _stderrFileName)
454 std::string smartCmd(_Command);
460 signal(SIGCHLD, SIG_DFL);
462 bp::child c(smartCmd, bp::std_out > _stdoutFileName, bp::std_err > _stderrFileName);
467 catch (std::exception& _e)
469 std::stringstream ss;
470 ss <<
"execute: " << _e.what();
471 throw std::runtime_error(ss.str());
476 inline void execute(
const std::string& _Command)
480 std::string smartCmd(_Command);
484 catch (std::exception& _e)
486 std::stringstream ss;
487 ss <<
"execute: " << _e.what();
488 throw std::runtime_error(ss.str());
495 inline pid_t
execute(
const std::string& _Command,
496 const std::chrono::seconds& _Timeout,
497 std::string* _output =
nullptr,
498 std::string* _errout =
nullptr,
499 int* _exitCode =
nullptr)
504 std::future<std::string> out_data;
505 std::future<std::string> err_data;
507 std::string smartCmd(_Command);
510 if (std::chrono::seconds(0) == _Timeout)
512 boost::process::child c(smartCmd);
518 bp::child c(smartCmd, bp::std_in.close(), bp::std_out > out_data, bp::std_err > err_data, ios);
520 while (c.valid() && !c.running())
524 throw std::runtime_error(
"Can't execute the given process.");
528 std::thread asioWorker{ [&ios]() {
533 catch (std::exception& _e)
556 auto start = std::chrono::steady_clock::now();
559 pid_t ret = ::waitpid(_pid, &status, WNOHANG | WUNTRACED);
560 if (ret < 0 || ret == _pid)
563 if ((std::chrono::steady_clock::now() - start) > _Timeout)
569 if (asioWorker.joinable())
571 throw std::runtime_error(
"Timeout has been reached, command execution will be terminated.");
576 if (asioWorker.joinable())
580 *_output = out_data.get();
583 *_errout = err_data.get();
586 *_exitCode = c.exit_code();
590 catch (std::exception& _e)
592 std::stringstream ss;
593 ss <<
"execute: " << _e.what();
594 throw std::runtime_error(ss.str());
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:251
~CPIDFile()
Definition: Process.h:94
std::vector< pid_t > vectorPid_t
Definition: Process.h:408
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:327
A PID-file helper.
Definition: Process.h:65
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:318
CPIDFile(const std::string &_FileName, pid_t _PID)
Definition: Process.h:68
bool operator()(CProcList::ProcContainer_t::value_type _pid, const std::string &_Name) const
Definition: Process.h:396
static void GetProcList(ProcContainer_t *_Procs)
Definition: Process.h:257
static pid_t GetPIDFromFile(const std::string &_FileName)
Definition: Process.h:100
~CProcStatus()
Definition: Process.h:323
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:410
std::set< pid_t > ProcContainer_t
Definition: Process.h:254
Definition: Process.h:394
Definition: MiscUtils.h:215
void smart_path(_T *_Path)
The function extends any environment variable found in the give path to its value.
Definition: SysHelper.h:93
std::string GetValue(const std::string &_KeyName) const
Definition: Process.h:355
bool IsProcessRunning(pid_t _PID)
The function checks, whether the process which corresponds to the given _PID can be found...
Definition: Process.h:56
pid_t execute(const std::string &_Command, const std::string &_stdoutFileName, const std::string &_stderrFileName)
Definition: Process.h:448
bool is_status_ok(int status)
Definition: Process.h:439
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:312