./src/lock_posix.cc
./src/date_time.cc
./src/signals_linux.cc
+ ./src/system.cc
+ ./src/resource_usage.cc
)
if (BUILD_BACKTRACE_SUPPORT)
endif()
if(ENABLE_LOG)
- target_link_libraries("Utils" log4cxx)
+ add_dependencies("Utils" liblog4cxx)
+ target_link_libraries("Utils" log4cxx -L${LOG4CXX_LIBS_DIRECTORY})
endif()
--- /dev/null
+/**
+ * Copyright (c) 2014, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SRC_COMPONENTS_UTILS_INCLUDE_UTILS_RESOURCE_USAGE_H_
+#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_RESOURCE_USAGE_H_
+
+#include <sys/resource.h>
+#if defined(__QNXNTO__)
+#include <sys/procfs.h>
+#endif
+
+#include <string>
+#include <iostream>
+
+#include "utils/logger.h"
+
+#define MAX_COMM_LEN 128
+#define MAX_CMDLINE_LEN 128
+
+namespace utils {
+
+struct ResourseUsage {
+ long long int utime;
+ long long int stime;
+ long long int memory;
+};
+
+class Resources {
+ public:
+ typedef uint32_t MemInfo;
+#if defined(__QNXNTO__)
+ typedef procfs_info PidStats;
+
+#elif defined(OS_LINUX)
+
+ struct PidStats {
+ int pid;
+ char comm[MAX_COMM_LEN];
+ char state;
+ int ppid;
+ int pgrp;
+ int session;
+ int tty_nr;
+ int tpgid;
+ unsigned int flags;
+ unsigned long minflt;
+ unsigned long cminflt;
+ unsigned long majflt;
+ unsigned long cmajflt;
+ unsigned long utime;
+ long stime;
+ long cutime;
+ long cstime;
+ long priority;
+ long nice;
+ long num_threads;
+ long itrealvalue;
+ unsigned long long starttime;
+ unsigned long vsize;
+ long rss;
+ unsigned long rsslim;
+ unsigned long startcode;
+ unsigned long endcode;
+ unsigned long startstack;
+ unsigned long kstkesp;
+ unsigned long kstkeip;
+ unsigned long signal;
+ unsigned long blocked;
+ unsigned long sigignore;
+ unsigned long sigcatch;
+ unsigned long wchan;
+ unsigned long nswap;
+ unsigned long cnswap;
+ int exit_signal;
+ int processor;
+ unsigned int rt_priority;
+ unsigned int policy;
+ unsigned long long delayacct_blkio_ticks;
+ unsigned long guest_time;
+ long int cguest_time;
+ };
+#else
+
+#endif
+ public:
+ /*
+ * @brief Returns current resource usage of process
+ * @return Raw pointer on ResourseUsage if success, otherwise return NULL
+ */
+ static ResourseUsage* getCurrentResourseUsage();
+
+private:
+
+ /*
+ * @brief reads /proc/PID/stat file on linux
+ * do not work on QNX ( return false, output wan't be changed )
+ * @param output - storage for result string ( there will be separated content of /proc/PID/stat )
+ * @return true on succes false onb fail
+ */
+ static bool ReadStatFile(std::string& output);
+
+ /*
+ * @brief Grab information about curent process
+ * @param output - storage for result struct
+ * @return true on succes false onb fail
+ */
+ static bool GetProcInfo(PidStats& output);
+
+ /*
+ * @brief Grab process memory information
+ * @param output - storage for result struct
+ * @return true on succes false onb fail
+ */
+ static bool GetMemInfo(MemInfo& output);
+
+ /*
+ * @brief return path to /proc/PID/stat file on linux
+ * return path to /proc/PID/as file on linux
+ * @return path to file
+ */
+ static std::string GetStatPath();
+
+ /*
+ * @brief return path to /proc/PID directry
+ * @return path to dir
+ */
+ static std::string GetProcPath();
+
+ /*
+ * path to /proc/ directory
+ */
+ static const char* proc;
+};
+
+}
+
+
+
+#endif /* SRC_COMPONENTS_UTILS_INCLUDE_UTILS_RESOURCE_USAGE_H_ */
--- /dev/null
+/**
+ * Copyright (c) 2014, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SRC_COMPONENTS_UTILS_INCLUDE_UTILS_SYSTEM_H_
+#define SRC_COMPONENTS_UTILS_INCLUDE_UTILS_SYSTEM_H_
+
+#include <string>
+#include <vector>
+
+namespace utils {
+
+/**
+ * Class to execute shell scripts
+ */
+class System {
+ public:
+ /**
+ * Constructs instantiation
+ * @param command name of command for executing
+ */
+ explicit System(const std::string& command);
+
+ /**
+ * Constructs instantiation
+ * @param file name of file for executing
+ * @param command name of command
+ */
+ System(const std::string& file, const std::string& command);
+
+ /**
+ * Adds argument
+ * @param arg argument of command
+ * @return itself object
+ */
+ System& Add(const std::string& arg);
+
+ /**
+ * Executes command as new child process
+ * @return true if success
+ */
+ bool Execute();
+
+ /**
+ * Executes command
+ * @param wait if this flag is true then wait until command is terminated
+ * @return true if success
+ */
+ bool Execute(bool wait);
+
+ private:
+ /**
+ * Command for executing
+ */
+ std::string command_;
+
+ /**
+ * List of arguments
+ */
+ std::vector<std::string> argv_;
+};
+
+} // utils
+
+#endif // SRC_COMPONENTS_UTILS_INCLUDE_UTILS_SYSTEM_H_
--- /dev/null
+#include "utils/resource_usage.h"
+#if defined(__QNXNTO__)
+#include <dirent.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <sys/neutrino.h>
+#include <sys/procfs.h>
+#include <sys/stat.h>
+#include <sys/trace.h>
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+#include <sys/resource.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sstream>
+#include "utils/file_system.h"
+
+namespace utils {
+
+CREATE_LOGGERPTR_GLOBAL(logger_, "Utils")
+
+const char* Resources::proc = "/proc/";
+
+ResourseUsage* Resources::getCurrentResourseUsage() {
+ PidStats pid_stats;
+ if (false == GetProcInfo(pid_stats)) {
+ LOG4CXX_ERROR(logger_, "Failed to get cpu proc info");
+ return NULL;
+ }
+ MemInfo mem_info;
+ if (false == GetMemInfo(mem_info)) {
+ LOG4CXX_ERROR(logger_, "Failed to get memory info");
+ return NULL;
+ }
+ ResourseUsage* usage = new ResourseUsage();
+ usage->utime = pid_stats.utime;
+ usage->stime = pid_stats.stime;
+ usage->memory = static_cast<long long int>(mem_info);
+ return usage;
+}
+
+bool Resources::ReadStatFile(std::string& output) {
+ std::string filename = GetStatPath();
+ if (false == file_system::FileExists(filename)) {
+ return false;
+ }
+ if (false == file_system::ReadFile(filename,output)) {
+ return false;
+ }
+ return true;
+}
+
+bool Resources::GetProcInfo(Resources::PidStats& output) {
+#if defined(OS_LINUX)
+ std::string proc_buf;
+ if (false == ReadStatFile(proc_buf)) {
+ return false;
+ }
+ uint32_t num_succes = sscanf(proc_buf.c_str(),
+ "%d" //pid
+ " %*s"//com
+ " %c" //state
+ " %d" //ppid
+ " %d" //pgrp
+ " %d" //session
+ " %d" //tty_nr
+ " %d" //tpgid
+ " %u" //flags
+ " %lu" //minflt
+ " %lu" //cminflt
+ " %lu" //majflt
+ " %lu" //cmajflt
+ " %lu" //utime
+ " %lu" //stime
+ " %ld" //cutime
+ " %ld" //cstime
+ " %ld" //priority
+ " %ld" //nice
+ " %ld" //num_threads
+ " %ld" //itrealvalue
+ " %llu" //starttime
+ " %lu" //vsize
+ " %ld" //rss
+ " %lu" //rsslim
+ " %lu" //startcode
+ " %lu" //endcode
+ " %lu" //startstack
+ " %lu" //kstkesp
+ " %lu" //kstkip
+ " %lu" //signal
+ " %lu" //blocked
+ " %lu" //sigignore
+ " %lu" //sigcatch
+ " %lu" //wchan
+ " %lu" //nswap
+ " %lu" //cnswap
+ " %d" //exit_signal
+ " %d" //processor
+ " %u" //rt_priority
+ " %u" //policy
+ " %llu" //delayacct_blkio_ticks
+ " %lu" //guest_time
+ " %ld" //cguest_time
+ ,&(output.pid), &(output.state), &(output.ppid), &(output.pgrp), &(output.session),
+ &(output.tty_nr), &(output.tpgid), &(output.flags), &(output.minflt), &(output.cminflt),
+ &(output.majflt), &(output.cmajflt), &(output.utime), &(output.stime), &(output.cutime),
+ &(output.cstime), &(output.priority), &( output.nice), &(output.num_threads), &(output.itrealvalue),
+ &(output.starttime), &(output.vsize), &(output.rss), &(output.rsslim), &(output.startcode),
+ &(output.endcode), &(output.startstack), &(output.kstkesp), &(output.kstkeip), &(output.signal),
+ &(output.blocked), &(output.sigignore), &(output.sigcatch), &(output.wchan), &(output.nswap),
+ &(output.cnswap), &(output.exit_signal), &(output.processor), &(output.rt_priority), &(output.policy),
+ &(output.delayacct_blkio_ticks), &(output.guest_time), &(output.cguest_time)
+ );
+ if(num_succes != 43) { // 43 is number of iteams in Resources::PidStats
+ LOG4CXX_ERROR(logger_, "Couldn't parse all iteams in /proc/PID/stat file");
+ return false;
+ }
+ return true;
+#elif defined(__QNXNTO__)
+ int fd = open(GetProcPath().c_str(), O_RDONLY);
+ if (0 >= fd) {
+ LOG4CXX_ERROR(logger_, "Failed open process proc file : " << GetProcPath() <<
+ "; error no : " << strerror( errno ) );
+ return false;
+ }
+ devctl(fd, DCMD_PROC_INFO, &output, sizeof(output), 0);
+ close(fd);
+ return true;
+#endif
+}
+
+bool Resources::GetMemInfo(Resources::MemInfo &output) {
+ bool result = false;
+ #if defined(OS_LINUX)
+ Resources::PidStats pid_stat;
+ if (false == GetProcInfo(pid_stat)) {
+ LOG4CXX_ERROR(logger_, "Failed to get proc info");
+ result = false;
+ } else {
+ output = pid_stat.rss;
+ result = true;
+ }
+
+#elif defined(__QNXNTO__)
+ std::string as_path = GetStatPath();
+ struct stat st;
+ struct _dir* proc_dir = 0;
+ struct dirent* proc_entry = 0;
+ if (0 == (proc_dir = opendir(proc))) {
+ LOG4CXX_ERROR(logger_, "Unable to access to " << proc);
+ result = false;
+ return result;
+ }
+ if (0 == (proc_entry = readdir(proc_dir))) {
+ LOG4CXX_ERROR(logger_, "Unable to read : " << proc_dir);
+ result = false;
+ return result;
+ }
+ closedir(proc_dir);
+ if (-1 == stat(as_path.c_str(), &st) || 0 == st.st_size) {
+ LOG4CXX_ERROR(logger_, "Unable to stat : " << as_path.c_str());
+ result = false;
+ return result;
+ }
+ output = st.st_size;
+ result = true;
+#endif
+ return result;
+}
+
+std::string Resources::GetStatPath() {
+ std::string filename;
+#if defined(OS_LINUX)
+ filename = GetProcPath() + "/stat";
+#elif defined(__QNXNTO__)
+ filename = GetProcPath() + "/as";
+#endif
+ return filename;
+}
+
+std::string Resources::GetProcPath() {
+ char buffer[1024];
+ pid_t my_pid = getpid();
+ snprintf(buffer, sizeof(buffer), "%s%d/", proc , my_pid);
+ std::string filename(buffer);
+ return filename;
+}
+
+} // namespace utils
--- /dev/null
+/**
+ * Copyright (c) 2014, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the Ford Motor Company nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "utils/system.h"
+
+#ifdef __QNX__
+# include <process.h>
+#else // __QNX__
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <sys/stat.h>
+# include <fcntl.h>
+# include <unistd.h>
+#endif // __QNX__
+
+#include <algorithm>
+#include <functional>
+
+#include "utils/logger.h"
+
+namespace utils {
+
+CREATE_LOGGERPTR_LOCAL(logger_, "Utils")
+
+struct GetCString {
+ char * operator ()(const std::string& string) {
+ return const_cast<char*>(string.c_str());
+ }
+};
+
+System::System(const std::string& command)
+ : command_(command) {
+ argv_.push_back(command);
+}
+
+System::System(const std::string& file, const std::string& command)
+ : command_(file) {
+ argv_.push_back(command);
+}
+
+bool System::Execute() {
+ return Execute(false);
+}
+
+System& System::Add(const std::string& arg) {
+ argv_.push_back(arg);
+ return *this;
+}
+
+#ifdef __QNX__
+
+bool System::Execute(bool wait) {
+ size_t size = argv_.size();
+ char * *argv = new char*[size + 1];
+ std::transform(argv_.begin(), argv_.end(), argv, GetCString());
+ argv[size] = NULL;
+
+ int mode = wait ? P_WAIT : P_NOWAIT;
+ int ret = spawnvp(mode, command_.c_str(), argv);
+ delete[] argv;
+
+ if (ret == -1) {
+ LOG4CXX_ERROR(logger_, "Can't execute command: " << command_);
+ return false;
+ }
+
+ if (wait) {
+ return WEXITSTATUS(ret) == 0;
+ }
+
+ return true;
+}
+
+#else // __QNX__
+
+bool System::Execute(bool wait) {
+ // Create a child process.
+ pid_t pid_command = fork();
+
+ switch (pid_command) {
+ case -1: { // Error
+ LOG4CXX_FATAL(logger_, "fork() failed!");
+ return false;
+ }
+ case 0: { // Child process
+ int32_t fd_dev0 = open("/dev/null", O_RDWR, S_IWRITE);
+ if (0 > fd_dev0) {
+ LOG4CXX_FATAL(logger_, "Open dev0 failed!");
+ return false;
+ }
+ // close input/output file descriptors.
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+
+ // move input/output to /dev/null.
+ dup2(fd_dev0, STDIN_FILENO);
+ dup2(fd_dev0, STDOUT_FILENO);
+ dup2(fd_dev0, STDERR_FILENO);
+
+ size_t size = argv_.size();
+ char * *argv = new char*[size + 1];
+ std::transform(argv_.begin(), argv_.end(), argv, GetCString());
+ argv[size] = NULL;
+
+ // Execute the program.
+ if (execvp(command_.c_str(), argv) == -1) {
+ LOG4CXX_ERROR(logger_, "Can't execute command: " << command_);
+ _exit(EXIT_FAILURE);
+ }
+ delete[] argv;
+
+ return true;
+ }
+ default: { /* Parent process */
+ LOG4CXX_INFO(logger_, "Process created with pid " << pid_command);
+ if (wait) {
+ int status;
+ pid_t wait_pid;
+ do {
+ wait_pid = waitpid(pid_command, &status, WUNTRACED | WCONTINUED);
+ if (wait_pid == -1) {
+ LOG4CXX_ERROR_WITH_ERRNO(logger_, "Can't wait");
+ _exit(EXIT_FAILURE);
+ return false;
+ }
+ } while (!WIFEXITED(status) && !WIFSIGNALED(status));
+ return WEXITSTATUS(status) == 0;
+ }
+
+ return true;
+ }
+ }
+}
+
+#endif // __QNX__
+
+} // utils