LinuxProcMgr.cc
Go to the documentation of this file.
1 // ============================================================
2 //
3 // LinuxProcInfo
4 //
5 // ============================================================
6 
10 #include "hep_concurrency/assert_only_one_thread.h"
11 
12 #include <cerrno>
13 #include <cstring>
14 #include <regex>
15 #include <sstream>
16 
17 extern "C" {
18 #include <unistd.h>
19 }
20 
21 namespace {
22 
23  // helper to ignore tokens in an istream
24  struct token_ignore {
25  explicit token_ignore(const unsigned ntokens) : ntokens_{ntokens} {}
26  unsigned ntokens_;
27  };
28 
29  std::istream&
30  operator>>(std::istream& is, token_ignore const&& ig)
31  {
33  unsigned i{};
34  while (i++ < ig.ntokens_)
35  is >> tmp;
36  return is;
37  }
38 
39  // NB: fclose must be called on the returned file descriptor.
40  auto
41  new_proc_file_descriptor(pid_t const pid)
42  {
43  std::ostringstream ost;
44  ost << "/proc/" << pid << "/stat";
45 
46  auto file = fopen(ost.str().c_str(), "r");
47  if (file == nullptr) {
49  << " Failed to open: " << ost.str() << '\n'
50  << " errno: " << errno << " (" << std::strerror(errno) << ")\n";
51  }
52  return file;
53  }
54 
55 } // namespace
56 
57 namespace art {
58 
59  LinuxProcMgr::LinuxProcMgr() noexcept(false)
60  : pid_{getpid()}
61  , pgSize_{sysconf(_SC_PAGESIZE)}
62  , file_{new_proc_file_descriptor(pid_)}
63  {}
64 
65  LinuxProcMgr::~LinuxProcMgr() noexcept { fclose(file_); }
66 
67  //=======================================================
69  LinuxProcMgr::getCurrentData() const noexcept(false)
70  {
71  HEP_CONCURRENCY_ASSERT_ONLY_ONE_THREAD();
72 
73  int const seek_result{fseek(file_, 0, SEEK_SET)};
74  if (seek_result != 0) {
76  "Error while retrieving Linux proc data."}
77  << "\nCould not reset position indicator while retrieving proc "
78  "stat information.\n";
79  }
80 
81  char buf[400];
82  size_t const cnt{fread(buf, 1, sizeof(buf), file_)};
83 
84  if (cnt == 0) {
86  "Error while retrieving Linux proc data."}
87  << "\nCould not read proc stat information.\n";
88  }
89 
90  buf[cnt] = '\0';
91 
94 
95  std::istringstream iss{buf};
96  iss >> token_ignore(22) >> vsize >> rss;
97 
98  return LinuxProcData::make_proc_tuple(vsize, rss * pgSize_);
99  }
100 
101  //=======================================================
102  double
103  LinuxProcMgr::getStatusData_(std::string const& field) const noexcept(false)
104  {
105  HEP_CONCURRENCY_ASSERT_ONLY_ONE_THREAD();
106 
107  std::ostringstream ost;
108  ost << "/proc/" << pid_ << "/status";
109 
110  auto file = fopen(ost.str().c_str(), "r");
111  if (file == nullptr) {
112  throw Exception{errors::Configuration} << " Failed to open: " << ost.str()
113  << std::endl;
114  }
115 
116  double value{};
117  std::regex const pattern{"^" + field + R"(:\s*(\d+)\s*kB)"};
118  while (!feof(file)) {
119  char buffer[128];
120  if (fgets(buffer, sizeof(buffer), file) != nullptr) {
121  std::cmatch cm;
122  if (std::regex_search(buffer, cm, pattern)) {
123  // Reported value from proc (although labeled 'kB') is
124  // actually in KiB. Will convert to base-10 MB.
125  value = std::stod(cm.str(1)) * LinuxProcData::KiB / LinuxProcData::MB;
126  break;
127  }
128  }
129  }
130  fclose(file);
131  return value;
132  }
133 
134 } // namespace art
static constexpr double cm
Definition: Units.h:68
std::string string
Definition: nybbler.cc:12
int errno
Contains the last error code.
Definition: structcmd.h:53
string tmp
Definition: languages.py:63
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
QDataStream & operator>>(QDataStream &s, QByteArray &a)
Definition: qcstring.cpp:605
std::string pattern
Definition: regex_t.cc:35
std::tuple< vsize_t, rss_t > proc_tuple
Definition: LinuxProcData.h:90
QTextStream & endl(QTextStream &s)