monitor.cpp
Go to the documentation of this file.
1 // Monitors execution of a launch file
2 // Author: Max Schwarz <max.schwarz@uni-bonn.de>
3 
4 #include "monitor.h"
5 
6 #include <ros/package.h>
7 #include <ros/node_handle.h>
8 #include <ros/param.h>
9 
10 #include <cstdarg>
11 #include <cstdio>
12 #include <fstream>
13 
14 #include <boost/regex.hpp>
15 #include <boost/algorithm/string/trim.hpp>
16 #include <boost/filesystem.hpp>
17 
18 #include <yaml-cpp/yaml.h>
19 
20 #include <fmt/format.h>
21 
22 #include "linux_process_info.h"
23 
24 template<typename... Args>
25 std::runtime_error error(const char* fmt, const Args& ... args)
26 {
27  return std::runtime_error(fmt::format(fmt, args...));
28 }
29 
30 namespace rosmon
31 {
32 namespace monitor
33 {
34 
36  : m_config(std::move(config))
37  , m_fdWatcher(std::move(watcher))
38  , m_ok(true)
39 {
40  for(auto& launchNode : m_config->nodes())
41  {
42  auto node = std::make_shared<NodeMonitor>(launchNode, m_fdWatcher, m_nh);
43 
44  node->logMessageSignal.connect(logMessageSignal);
45 
46  if(launchNode->required())
47  {
48  node->exitedSignal.connect(
49  boost::bind(&Monitor::handleRequiredNodeExit, this, _1)
50  );
51  }
52 
53  m_nodes.push_back(node);
54  }
55 
56 #if HAVE_STEADYTIMER
58 #else
60 #endif
61  ros::WallDuration(1.0),
62  boost::bind(&Monitor::updateStats, this)
63  );
64 }
65 
67 {
68  {
69  std::vector<std::string> paramNames;
70 
71  for(auto& node : m_config->nodes())
72  {
73  if(node->clearParams())
74  {
75  std::string paramNamespace = node->namespaceString() + "/" + node->name() + "/";
76 
77  log("Deleting parameters in namespace {}", paramNamespace.c_str());
78 
79  if(paramNames.empty())
80  {
81  if(!ros::param::getParamNames(paramNames))
82  throw error("Could not get list of parameters for clear_param");
83  }
84 
85  for(auto& param : paramNames)
86  {
87  if(param.substr(0, paramNamespace.length()) == paramNamespace)
88  {
90  }
91  }
92  }
93  }
94  }
95 
96  for(auto& param : m_config->parameters())
97  m_nh.setParam(param.first, param.second);
98 }
99 
101 {
102  for(auto& node : m_nodes)
103  {
104  node->start();
105  }
106 }
107 
109 {
110  for(auto& node : m_nodes)
111  node->shutdown();
112 }
113 
115 {
116  log("Killing the following nodes, which are refusing to exit:\n");
117  for(auto& node : m_nodes)
118  {
119  if(node->running())
120  {
121  log(" - {}\n", node->name());
122  node->forceExit();
123  }
124  }
125 }
126 
128 {
129  bool allShutdown = true;
130  for(auto& node : m_nodes)
131  {
132  if(node->running())
133  allShutdown = false;
134  }
135 
136  return allShutdown;
137 }
138 
140 {
141  double timeout = 0.0;
142  // Find the biggest timeout
143  for(auto& node : m_nodes)
144  if(node->stopTimeout() > timeout)
145  timeout = node->stopTimeout();
146  return timeout;
147 }
148 
149 
150 void Monitor::handleRequiredNodeExit(const std::string& name)
151 {
152  log("Required node '{}' exited, shutting down...", name);
153  m_ok = false;
154 }
155 
156 template<typename... Args>
157 void Monitor::log(const char* fmt, const Args& ... args)
158 {
160  "[rosmon]",
161  fmt::format(fmt, args...)
162  );
163 }
164 
166 {
167  namespace fs = boost::filesystem;
168 
169  fs::directory_iterator it("/proc");
170  fs::directory_iterator end;
171 
172  std::map<int, NodeMonitor::Ptr> nodeMap;
173  for(auto& node : m_nodes)
174  {
175  if(node->pid() != -1)
176  nodeMap[node->pid()] = node;
177 
178  node->beginStatUpdate();
179  }
180 
181  for(auto& procInfo : m_processInfos)
182  procInfo.second.active = false;
183 
184  for(; it != end; ++it)
185  {
186  fs::path statPath = (*it) / "stat";
187 
189  if(!process_info::readStatFile(statPath.c_str(), &stat))
190  continue;
191 
192  // Find corresponding node by the process group ID
193  // (= process ID of the group leader process)
194  auto it = nodeMap.find(stat.pgrp);
195  if(it == nodeMap.end())
196  continue;
197 
198  auto& node = it->second;
199 
200  // We need to store the stats and subtract the last one to get a time
201  // delta
202  auto infoIt = m_processInfos.find(stat.pid);
203  if(infoIt == m_processInfos.end())
204  {
205  ProcessInfo info;
206  info.stat = stat;
207  info.active = true;
208  m_processInfos[stat.pid] = info;
209  continue;
210  }
211 
212  const auto& oldStat = infoIt->second.stat;
213 
214  node->addCPUTime(stat.utime - oldStat.utime, stat.stime - oldStat.stime);
215  node->addMemory(stat.mem_rss);
216 
217  infoIt->second.active = true;
218  infoIt->second.stat = stat;
219  }
220 
221  for(auto& node : m_nodes)
222  node->endStatUpdate(process_info::kernel_hz());
223 
224  // Clean up old processes
225  for(auto it = m_processInfos.begin(); it != m_processInfos.end();)
226  {
227  if(!it->second.active)
228  it = m_processInfos.erase(it);
229  else
230  it++;
231  }
232 }
233 
234 }
235 }
ros::WallTimer m_statTimer
Definition: monitor.h:75
ROSCPP_DECL bool getParamNames(std::vector< std::string > &keys)
bool param(const std::string &param_name, T &param_val, const T &default_val)
jiffies_t stime
Total time spent in kernel space.
std::runtime_error error(const char *fmt, const Args &...args)
Definition: monitor.cpp:25
std::map< int, ProcessInfo > m_processInfos
Definition: monitor.h:78
process_info::ProcessStat stat
Definition: monitor.h:52
boost::signals2::signal< void(std::string, std::string)> logMessageSignal
Definition: monitor.h:48
bool readStatFile(const char *filename, ProcessStat *stat)
SteadyTimer createSteadyTimer(WallDuration period, void(T::*callback)(const SteadyTimerEvent &), T *obj, bool oneshot=false, bool autostart=true) const
std::vector< NodeMonitor::Ptr > m_nodes
Definition: monitor.h:68
Monitor(launch::LaunchConfig::ConstPtr config, FDWatcher::Ptr watcher)
Definition: monitor.cpp:35
WallTimer createWallTimer(WallDuration period, void(T::*callback)(const WallTimerEvent &), T *obj, bool oneshot=false, bool autostart=true) const
ros::NodeHandle m_nh
Definition: monitor.h:65
FDWatcher::Ptr m_fdWatcher
Definition: monitor.h:66
std::shared_ptr< const LaunchConfig > ConstPtr
ROSCPP_DECL bool del(const std::string &key)
jiffies_t utime
Total time spent in userspace.
jiffies_t kernel_hz()
Number of kernel jiffies per second.
std::size_t mem_rss
Resident memory size in bytes.
void handleRequiredNodeExit(const std::string &name)
Definition: monitor.cpp:150
launch::LaunchConfig::ConstPtr m_config
Definition: monitor.h:63
unsigned long pgrp
Process group ID.
void setParam(const std::string &key, const XmlRpc::XmlRpcValue &v) const
void log(const char *fmt, const Args &...args)
Definition: monitor.cpp:157


rosmon_core
Author(s): Max Schwarz
autogenerated on Wed Jul 10 2019 03:10:12