13 #include <sys/types.h> 18 #if defined(__APPLE__) 19 #include <sys/sysctl.h> 37 #include <boost/asio.hpp> 38 #include <boost/asio/deadline_timer.hpp> 39 #pragma clang diagnostic push 40 #pragma clang diagnostic ignored "-Wunused-variable" 41 #include <boost/process.hpp> 42 #pragma clang diagnostic pop 44 namespace bp = boost::process;
45 namespace bio = boost::asio;
63 return !(::kill(_PID, 0) == -1 && errno == ESRCH);
73 CPIDFile(
const std::string& _FileName, pid_t _PID)
74 : m_FileName(_FileName)
76 if (!_FileName.empty() && _PID > 0)
84 throw std::runtime_error(
"Error creating pidfile. The process corresponding to pidfile \"" +
85 _FileName +
"\" is still running");
89 std::ofstream f(m_FileName.c_str());
91 throw std::runtime_error(
"can't create PID file: " + m_FileName);
101 if (!m_FileName.empty())
102 ::unlink(m_FileName.c_str());
107 std::ifstream f(_FileName.c_str());
118 std::string m_FileName;
121 #if defined(__APPLE__) 132 typedef std::set<pid_t> ProcContainer_t;
135 static void getAllPIDsForProcessName(
const std::string& _processName,
136 ProcContainer_t* _pidContainer,
137 bool _filterForRealUserID =
false)
143 int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
147 struct kinfo_proc* BSDProcInfo = NULL;
149 if (_processName.empty())
154 _pidContainer->clear();
160 error = sysctl(mib, 3, NULL, &buffSize, NULL, 0);
162 throw system_error(
"Error occurred while retrieving a running processes list");
164 BSDProcInfo = (
struct kinfo_proc*)malloc(buffSize);
166 if (BSDProcInfo == NULL)
168 "Error occurred while retrieving a running processes list. Unable to allocate the buffer.");
170 error = sysctl(mib, 3, BSDProcInfo, &buffSize, NULL, 0);
192 uid_t userid = getuid();
194 const size_t processCount = buffSize /
sizeof(
struct kinfo_proc);
195 for (
size_t i = 0; i < processCount; ++i)
198 const pid_t pid = BSDProcInfo[i].kp_proc.p_pid;
200 const std::string name = BSDProcInfo[i].kp_proc.p_comm;
202 const uid_t uid = BSDProcInfo[i].kp_eproc.e_pcred.p_ruid;
204 if ((pid > 0) && (name == _processName))
206 if (!_filterForRealUserID)
207 _pidContainer->insert(pid);
208 else if (uid == userid)
209 _pidContainer->insert(pid);
216 static bool pidExists(
int _pid)
218 int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
220 if (sysctl(name, 4, NULL, &length, NULL, 0))
221 throw system_error(
"Unable to call sysctl in the pidExists function.");
222 kinfo_proc* result = (kinfo_proc*)malloc(length);
223 if (sysctl(name, 4, result, &length, NULL, 0))
224 throw system_error(
"Unable to call sysctl in the pidExists function.");
225 int i, procCount = length /
sizeof(kinfo_proc);
226 for (i = 0; i < procCount; ++i)
228 kinfo_proc* test = &result[i];
230 if (test->kp_proc.p_pid == _pid)
255 #if !defined(__APPLE__) 265 throw std::invalid_argument(
"CProcList::GetProcList: Input container is NULL");
269 struct dirent** namelist;
271 int n = scandir(
"/proc", &namelist, CheckDigit, alphasort);
278 for (
int i = 0; i < n; ++i)
280 std::stringstream ss(namelist[i]->d_name);
291 static int CheckDigit(
const struct dirent* _d)
293 const std::string sName(_d->d_name);
295 return (sName.end() == std::find_if(sName.begin(), sName.end(), std::not1(
IsDigit())));
300 #if !defined(__APPLE__) 319 typedef std::shared_ptr<std::ifstream> ifstream_ptr;
320 typedef std::map<std::string, std::string> keyvalue_t;
326 regcomp(&m_re,
"(.*):(.*)", REG_EXTENDED);
338 std::stringstream ss;
339 ss <<
"/proc/" << _PId <<
"/status";
340 m_f = ifstream_ptr(
new std::ifstream(ss.str().c_str()));
360 std::string
GetValue(
const std::string& _KeyName)
const 363 std::string sKey(_KeyName);
366 keyvalue_t::const_iterator iter = m_values.find(sKey);
367 return (m_values.end() == iter ? std::string() : iter->second);
371 bool _Parser(
const std::string& _sVal)
373 regmatch_t PMatch[3];
374 if (0 != regexec(&m_re, _sVal.c_str(), 3, PMatch, 0))
376 std::string sKey(_sVal.c_str() + PMatch[1].rm_so, PMatch[1].rm_eo - PMatch[1].rm_so);
377 std::string sValue(_sVal.c_str() + PMatch[2].rm_so, PMatch[2].rm_eo - PMatch[2].rm_so);
381 trim<std::string>(&sValue,
'\t');
382 trim<std::string>(&sValue,
' ');
384 m_values.insert(keyvalue_t::value_type(sKey, sValue));
398 #if !defined(__APPLE__) 399 struct SFindName :
public std::binary_function<CProcList::ProcContainer_t::value_type, std::string, bool>
401 bool operator()(CProcList::ProcContainer_t::value_type _pid,
const std::string& _Name)
const 405 return (p.
GetValue(
"Name") == _Name);
418 #if defined(__APPLE__) 419 CFindProcess::ProcContainer_t container;
420 CFindProcess::getAllPIDsForProcessName(_Srv, &container, _filterForRealUserID);
421 copy(container.begin(), container.end(), std::back_inserter(retVal));
426 CProcList::ProcContainer_t::const_iterator iter = pids.begin();
429 iter = std::find_if(iter, pids.end(), std::bind2nd(
SFindName(), _Srv));
430 if (pids.end() == iter)
433 retVal.push_back(*iter);
446 return WIFEXITED(status) && WEXITSTATUS(status) == 0;
453 inline pid_t
execute(
const std::string& _Command,
454 const std::string& _stdoutFileName,
455 const std::string& _stderrFileName)
459 std::string smartCmd(_Command);
466 std::signal(SIGCHLD, SIG_DFL);
469 bp::child c(smartCmd, bp::std_out > _stdoutFileName, bp::std_err > _stderrFileName);
475 catch (std::exception& _e)
477 std::stringstream ss;
478 ss <<
"execute: " << _e.what();
479 throw std::runtime_error(ss.str());
484 inline void execute(
const std::string& _Command)
488 std::string smartCmd(_Command);
492 catch (std::exception& _e)
494 std::stringstream ss;
495 ss <<
"execute: " << _e.what();
496 throw std::runtime_error(ss.str());
503 inline pid_t
execute(
const std::string& _Command,
504 const std::chrono::seconds& _Timeout,
505 std::string* _output =
nullptr,
506 std::string* _errout =
nullptr,
507 int* _exitCode =
nullptr)
511 std::string smartCmd(_Command);
514 if (std::chrono::seconds(0) == _Timeout)
516 boost::process::child c(smartCmd);
522 boost::asio::io_service ios;
523 bp::async_pipe outPipe(ios);
524 bp::async_pipe errPipe(ios);
525 boost::asio::streambuf outBuf;
526 boost::asio::streambuf errBuf;
528 boost::asio::deadline_timer watchdog{ ios, boost::posix_time::seconds(_Timeout.count()) };
530 bp::child c(smartCmd,
532 bp::std_out > outPipe,
533 bp::std_err > errPipe,
535 bp::on_exit([&](
int exit,
const std::error_code& ec_in) {
543 throw std::runtime_error(
"Can't execute the given process.");
545 boost::asio::async_read(outPipe, outBuf, [](
const boost::system::error_code& ec, std::size_t size) {});
546 boost::asio::async_read(errPipe, errBuf, [](
const boost::system::error_code& ec, std::size_t size) {});
548 bool errorFlag(
false);
549 watchdog.async_wait([&](boost::system::error_code ec) {
568 throw std::runtime_error(
"Timeout has been reached, command execution will be terminated.");
571 *_exitCode = c.exit_code();
574 _output->assign(std::istreambuf_iterator<char>(&outBuf), std::istreambuf_iterator<char>());
577 _errout->assign(std::istreambuf_iterator<char>(&errBuf), std::istreambuf_iterator<char>());
581 catch (std::exception& _e)
583 std::stringstream ss;
584 ss <<
"execute: " << _e.what();
585 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:256
~CPIDFile()
Definition: Process.h:99
std::vector< pid_t > vectorPid_t
Definition: Process.h:413
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:249
void Open(pid_t _PId)
Definition: Process.h:332
A PID-file helper.
Definition: Process.h:70
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:323
CPIDFile(const std::string &_FileName, pid_t _PID)
Definition: Process.h:73
bool operator()(CProcList::ProcContainer_t::value_type _pid, const std::string &_Name) const
Definition: Process.h:401
static void GetProcList(ProcContainer_t *_Procs)
Definition: Process.h:262
static pid_t GetPIDFromFile(const std::string &_FileName)
Definition: Process.h:105
~CProcStatus()
Definition: Process.h:328
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:415
std::set< pid_t > ProcContainer_t
Definition: Process.h:259
Definition: Process.h:399
Definition: MiscUtils.h:219
void smart_path(_T *_Path)
The function extends any environment variable found in the give path to its value.
Definition: SysHelper.h:95
std::string GetValue(const std::string &_KeyName) const
Definition: Process.h:360
bool IsProcessRunning(pid_t _PID)
The function checks, whether the process which corresponds to the given _PID can be found.
Definition: Process.h:57
pid_t execute(const std::string &_Command, const std::string &_stdoutFileName, const std::string &_stderrFileName)
Definition: Process.h:453
bool is_status_ok(int status)
Definition: Process.h:444
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:317