5 #ifndef _DDS_PROCESS_H_ 6 #define _DDS_PROCESS_H_ 14 #include <sys/types.h> 18 #if defined(__APPLE__) 19 #include <sys/sysctl.h> 26 #include <boost/asio.hpp> 27 #include <boost/asio/deadline_timer.hpp> 28 #include <boost/filesystem/operations.hpp> 29 #include <boost/process.hpp> 37 namespace bp = boost::process;
38 namespace bio = boost::asio;
39 namespace fs = boost::filesystem;
57 return !(::kill(_PID, 0) == -1 && errno == ESRCH);
67 CPIDFile(
const std::string& _FileName, pid_t _PID)
68 : m_FileName(_FileName)
70 if (!_FileName.empty() && _PID > 0)
78 throw std::runtime_error(
"Error creating pidfile. The process corresponding to pidfile \"" +
79 _FileName +
"\" is still running");
83 std::ofstream f(m_FileName.c_str());
85 throw std::runtime_error(
"can't create PID file: " + m_FileName);
95 if (!m_FileName.empty())
96 ::unlink(m_FileName.c_str());
101 std::ifstream f(_FileName.c_str());
112 std::string m_FileName;
115 #if defined(__APPLE__) 126 typedef std::set<pid_t> ProcContainer_t;
129 static void getAllPIDsForProcessName(
const std::string& _processName,
130 ProcContainer_t* _pidContainer,
131 bool _filterForRealUserID =
false)
137 int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
141 struct kinfo_proc* BSDProcInfo = NULL;
143 if (_processName.empty())
148 _pidContainer->clear();
154 error = sysctl(mib, 3, NULL, &buffSize, NULL, 0);
156 throw system_error(
"Error occurred while retrieving a running processes list");
158 BSDProcInfo = (
struct kinfo_proc*)malloc(buffSize);
160 if (BSDProcInfo == NULL)
162 "Error occurred while retrieving a running processes list. Unable to allocate the buffer.");
164 error = sysctl(mib, 3, BSDProcInfo, &buffSize, NULL, 0);
186 uid_t userid = getuid();
188 const size_t processCount = buffSize /
sizeof(
struct kinfo_proc);
189 for (
size_t i = 0; i < processCount; ++i)
192 const pid_t pid = BSDProcInfo[i].kp_proc.p_pid;
194 const std::string name = BSDProcInfo[i].kp_proc.p_comm;
196 const uid_t uid = BSDProcInfo[i].kp_eproc.e_pcred.p_ruid;
198 if ((pid > 0) && (name == _processName))
200 if (!_filterForRealUserID)
201 _pidContainer->insert(pid);
202 else if (uid == userid)
203 _pidContainer->insert(pid);
210 static bool pidExists(
int _pid)
212 int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
214 if (sysctl(name, 4, NULL, &length, NULL, 0))
215 throw system_error(
"Unable to call sysctl in the pidExists function.");
216 kinfo_proc* result = (kinfo_proc*)malloc(length);
217 if (sysctl(name, 4, result, &length, NULL, 0))
218 throw system_error(
"Unable to call sysctl in the pidExists function.");
219 int i, procCount = length /
sizeof(kinfo_proc);
220 for (i = 0; i < procCount; ++i)
222 kinfo_proc* test = &result[i];
224 if (test->kp_proc.p_pid == _pid)
249 #if !defined(__APPLE__) 259 throw std::invalid_argument(
"CProcList::GetProcList: Input container is NULL");
263 struct dirent** namelist;
265 int n = scandir(
"/proc", &namelist, CheckDigit, alphasort);
272 for (
int i = 0; i < n; ++i)
274 std::stringstream ss(namelist[i]->d_name);
285 static int CheckDigit(
const struct dirent* _d)
287 const std::string sName(_d->d_name);
289 return (sName.end() == std::find_if(sName.begin(), sName.end(), std::not1(
IsDigit())));
294 #if !defined(__APPLE__) 313 typedef std::shared_ptr<std::ifstream> ifstream_ptr;
314 typedef std::map<std::string, std::string> keyvalue_t;
320 regcomp(&m_re,
"(.*):(.*)", REG_EXTENDED);
332 std::stringstream ss;
333 ss <<
"/proc/" << _PId <<
"/status";
334 m_f = ifstream_ptr(
new std::ifstream(ss.str().c_str()));
354 std::string
GetValue(
const std::string& _KeyName)
const 357 std::string sKey(_KeyName);
360 keyvalue_t::const_iterator iter = m_values.find(sKey);
361 return (m_values.end() == iter ? std::string() : iter->second);
365 bool _Parser(
const std::string& _sVal)
367 regmatch_t PMatch[3];
368 if (0 != regexec(&m_re, _sVal.c_str(), 3, PMatch, 0))
370 std::string sKey(_sVal.c_str() + PMatch[1].rm_so, PMatch[1].rm_eo - PMatch[1].rm_so);
371 std::string sValue(_sVal.c_str() + PMatch[2].rm_so, PMatch[2].rm_eo - PMatch[2].rm_so);
375 trim<std::string>(&sValue,
'\t');
376 trim<std::string>(&sValue,
' ');
378 m_values.insert(keyvalue_t::value_type(sKey, sValue));
392 #if !defined(__APPLE__) 393 struct SFindName :
public std::binary_function<CProcList::ProcContainer_t::value_type, std::string, bool>
395 bool operator()(CProcList::ProcContainer_t::value_type _pid,
const std::string& _Name)
const 399 return (p.
GetValue(
"Name") == _Name);
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,
451 std::string* _outputFilesAccessPermissions =
nullptr)
455 std::string smartCmd(_Command);
462 std::signal(SIGCHLD, SIG_DFL);
465 bp::child c(smartCmd, bp::std_out > _stdoutFileName, bp::std_err > _stderrFileName);
470 if (_outputFilesAccessPermissions && !_outputFilesAccessPermissions->empty())
472 const int perm = std::stoi(*_outputFilesAccessPermissions, 0, 8);
473 if (fs::exists(_stdoutFileName))
474 fs::permissions(_stdoutFileName, fs::perms(perm));
475 if (fs::exists(_stderrFileName))
476 fs::permissions(_stderrFileName, fs::perms(perm));
481 catch (std::exception& _e)
483 std::stringstream ss;
484 ss <<
"execute: " << _e.what();
485 throw std::runtime_error(ss.str());
490 inline void execute(
const std::string& _Command)
494 std::string smartCmd(_Command);
498 catch (std::exception& _e)
500 std::stringstream ss;
501 ss <<
"execute: " << _e.what();
502 throw std::runtime_error(ss.str());
509 inline pid_t
execute(
const std::string& _Command,
510 const std::chrono::seconds& _Timeout,
511 std::string* _output =
nullptr,
512 std::string* _errout =
nullptr,
513 int* _exitCode =
nullptr)
517 std::string smartCmd(_Command);
520 if (std::chrono::seconds(0) == _Timeout)
522 boost::process::child c(smartCmd);
528 boost::asio::io_service ios;
529 bp::async_pipe outPipe(ios);
530 bp::async_pipe errPipe(ios);
531 boost::asio::streambuf outBuf;
532 boost::asio::streambuf errBuf;
534 boost::asio::deadline_timer watchdog{ ios, boost::posix_time::seconds(_Timeout.count()) };
536 bp::child c(smartCmd,
538 bp::std_out > outPipe,
539 bp::std_err > errPipe,
542 [&](
int ,
const std::error_code& )
551 throw std::runtime_error(
"Can't execute the given process.");
553 boost::asio::async_read(
554 outPipe, outBuf, [](
const boost::system::error_code& , std::size_t ) {});
555 boost::asio::async_read(
556 errPipe, errBuf, [](
const boost::system::error_code& , std::size_t ) {});
558 bool errorFlag(
false);
560 [&](boost::system::error_code ec)
580 throw std::runtime_error(
"Timeout has been reached, command execution will be terminated.");
583 *_exitCode = c.exit_code();
586 _output->assign(std::istreambuf_iterator<char>(&outBuf), std::istreambuf_iterator<char>());
589 _errout->assign(std::istreambuf_iterator<char>(&errBuf), std::istreambuf_iterator<char>());
593 catch (std::exception& _e)
595 std::stringstream ss;
596 ss <<
"execute: " << _e.what();
597 throw std::runtime_error(ss.str());
Definition: MiscUtils.h:219
This class helps to retrieve process's information from /proc/<pid>/status.
Definition: Process.h:311
pid_t execute(const std::string &_Command, const std::string &_stdoutFileName, const std::string &_stderrFileName, std::string *_outputFilesAccessPermissions=nullptr)
Definition: Process.h:448
vectorPid_t getprocbyname(const std::string &_Srv, bool _filterForRealUserID=false)
_filterForRealUserID is an OS X specific argument
Definition: Process.h:410
bool IsProcessRunning(pid_t _PID)
The function checks, whether the process which corresponds to the given _PID can be found.
Definition: Process.h:51
std::vector< std::string > StringVector_t
An STL vector of strings.
Definition: def.h:112
void Open(pid_t _PId)
Definition: Process.h:326
CPIDFile(const std::string &_FileName, pid_t _PID)
Definition: Process.h:67
std::vector< pid_t > vectorPid_t
Definition: Process.h:407
This custom istream iterator helps to read input line by line without breaking lines after whitespace...
Definition: CustomIterator.h:24
bool is_status_ok(int status)
Definition: Process.h:439
std::set< pid_t > ProcContainer_t
Definition: Process.h:253
static void GetProcList(ProcContainer_t *_Procs)
Definition: Process.h:256
static pid_t GetPIDFromFile(const std::string &_FileName)
Definition: Process.h:99
~CProcStatus()
Definition: Process.h:322
~CPIDFile()
Definition: Process.h:93
CProcStatus()
Definition: Process.h:317
The system_error exception class retrieves a string, which represent the last error.
Definition: ErrorCode.h:76
A PID-file helper.
Definition: Process.h:64
Definition: Process.h:393
void smart_path(_T *_Path)
The function extends any environment variable found in the give path to its value.
Definition: SysHelper.h:95
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
_T & to_lower(_T &_str)
convert string to lower case.
Definition: MiscUtils.h:249
std::string GetValue(const std::string &_KeyName) const
Definition: Process.h:354
bool operator()(CProcList::ProcContainer_t::value_type _pid, const std::string &_Name) const
Definition: Process.h:395
This class is used to quarry a list of currently running processes.
Definition: Process.h:250
Definition: BoostHelper.h:14