Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-06-06 01:33:21

0001 // -*- C++ -*-
0002 //
0003 // Package:     Services
0004 // Class  :     ProcInfoFetcher
0005 //
0006 // Implementation:
0007 //     [Notes on implementation]
0008 //
0009 // Original Author:  Chris Jones
0010 //         Created:  Sun May  6 11:14:31 CDT 2012
0011 //
0012 
0013 // system include files
0014 
0015 // user include files
0016 
0017 #include <cstring>
0018 #include <cassert>
0019 #include <iostream>
0020 #include <array>
0021 #ifdef __linux__
0022 #include <malloc.h>
0023 #endif
0024 #include <sstream>
0025 //#include <stdio.h>
0026 #include <string>
0027 
0028 #include <fcntl.h>
0029 #include <unistd.h>
0030 
0031 #include "FWCore/Services/plugins/ProcInfoFetcher.h"
0032 #include "FWCore/Utilities/interface/EDMException.h"
0033 #include "FWCore/Utilities/interface/get_underlying_safe.h"
0034 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0035 
0036 //
0037 // constants, enums and typedefs
0038 //
0039 
0040 //
0041 // static data member definitions
0042 //
0043 
0044 namespace {
0045   struct linux_proc {
0046     int pid;  // %d
0047     std::string comm;
0048     char state;                    // %c
0049     int ppid;                      // %d
0050     int pgrp;                      // %d
0051     int session;                   // %d
0052     int tty;                       // %d
0053     int tpgid;                     // %d
0054     unsigned int flags;            // %u [before linux 2.6 %lu]
0055     unsigned long minflt;          // %lu
0056     unsigned long cminflt;         // %lu
0057     unsigned long majflt;          // %lu
0058     unsigned long cmajflt;         // %lu
0059     unsigned long utime;           // %lu
0060     unsigned long stime;           // %lu
0061     long cutime;                   // %ld
0062     long cstime;                   // %ld
0063     long priority;                 // %ld
0064     long nice;                     // %ld
0065     long num_threads;              // %ld
0066     long itrealvalue;              // %ld
0067     unsigned long long starttime;  // %llu [before linux 2.6 %d]
0068     unsigned long vsize;           // %lu
0069     long rss;                      // %ld
0070     unsigned long rlim;            // %lu
0071     unsigned long startcode;       // %lu
0072     unsigned long endcode;         // %lu
0073     unsigned long startstack;      // %lu
0074     unsigned long kstkesp;         // %lu
0075     unsigned long kstkeip;         // %lu
0076     unsigned long signal;          // %lu
0077     unsigned long blocked;         // %lu
0078     unsigned long sigignore;       // %lu
0079     unsigned long sigcatch;        // %lu
0080     unsigned long wchan;           // %lu
0081   };
0082 
0083   class Fetcher {
0084   public:
0085     friend Fetcher& operator>>(Fetcher&, int&);
0086     friend Fetcher& operator>>(Fetcher&, long&);
0087     friend Fetcher& operator>>(Fetcher&, unsigned int&);
0088     friend Fetcher& operator>>(Fetcher&, unsigned long&);
0089     friend Fetcher& operator>>(Fetcher&, unsigned long long&);
0090     friend Fetcher& operator>>(Fetcher&, char&);
0091     friend Fetcher& operator>>(Fetcher&, std::string&);
0092 
0093     explicit Fetcher(char* buffer) : buffer_(buffer), save_(nullptr), delims_(" \t\n\f\v\r") {}
0094 
0095   private:
0096     int getInt() {
0097       const char* t = getItem();
0098       //std::cout <<"int '"<<t <<"'"<<std::endl;
0099       return std::stoi(t);
0100     }
0101     long getLong() {
0102       const char* t = getItem();
0103       //std::cout <<"long '"<<t <<"'"<<std::endl;
0104       return std::stol(t);
0105     }
0106     unsigned int getUInt() {
0107       const char* t = getItem();
0108       //std::cout <<"uint '"<<t <<"'"<<std::endl;
0109       return std::stoul(t);
0110     }
0111     unsigned long getULong() {
0112       const char* t = getItem();
0113       //std::cout <<"ulong '"<<t <<"'"<<std::endl;
0114       return std::stoul(t);
0115     }
0116     unsigned long long getULongLong() {
0117       const char* t = getItem();
0118       //std::cout <<"ulong '"<<t <<"'"<<std::endl;
0119       return std::stoull(t);
0120     }
0121     char getChar() { return *getItem(); }
0122     std::string getString() { return std::string(getItem()); }
0123     char* getItem() {
0124       char* item = strtok_r(buffer_, delims_, &save());
0125       assert(item);
0126       buffer_ = nullptr;  // Null for subsequent strtok_r calls.
0127       return item;
0128     }
0129 
0130     char const* save() const { return get_underlying_safe(save_); }
0131     char*& save() { return get_underlying_safe(save_); }
0132 
0133     edm::propagate_const<char*> buffer_;
0134     edm::propagate_const<char*> save_;
0135     char const* const delims_;
0136   };
0137 
0138   Fetcher& operator>>(Fetcher& iFetch, int& oValue) {
0139     oValue = iFetch.getInt();
0140     return iFetch;
0141   }
0142   Fetcher& operator>>(Fetcher& iFetch, long& oValue) {
0143     oValue = iFetch.getLong();
0144     return iFetch;
0145   }
0146   Fetcher& operator>>(Fetcher& iFetch, unsigned int& oValue) {
0147     oValue = iFetch.getUInt();
0148     return iFetch;
0149   }
0150   Fetcher& operator>>(Fetcher& iFetch, unsigned long& oValue) {
0151     oValue = iFetch.getULong();
0152     return iFetch;
0153   }
0154   Fetcher& operator>>(Fetcher& iFetch, unsigned long long& oValue) {
0155     oValue = iFetch.getULongLong();
0156     return iFetch;
0157   }
0158   Fetcher& operator>>(Fetcher& iFetch, char& oValue) {
0159     oValue = iFetch.getChar();
0160     return iFetch;
0161   }
0162   Fetcher& operator>>(Fetcher& iFetch, std::string& oValue) {
0163     oValue = iFetch.getString();
0164     return iFetch;
0165   }
0166 }  // namespace
0167 
0168 namespace edm {
0169   namespace service {
0170 
0171     ProcInfoFetcher::ProcInfoFetcher() : pg_size_(sysconf(_SC_PAGESIZE)) {
0172 #ifdef __linux__
0173       std::ostringstream ost;
0174       ost << "/proc/" << getpid() << "/stat";
0175 
0176       if ((fd_ = open(ost.str().c_str(), O_RDONLY)) < 0) {
0177         throw Exception(errors::Configuration) << "Failed to open " << ost.str() << std::endl;
0178       }
0179 #endif
0180     }
0181     ProcInfoFetcher::~ProcInfoFetcher() {
0182 #ifdef LINUX
0183       close(fd_);
0184 #endif
0185     }
0186     ProcInfo ProcInfoFetcher::fetch() const {
0187       ProcInfo ret;
0188 
0189 #ifdef __linux__
0190       double pr_size = 0.0, pr_rssize = 0.0;
0191 
0192       linux_proc pinfo;
0193       int cnt;
0194 
0195       lseek(fd_, 0, SEEK_SET);
0196 
0197       std::array<char, 500> buf;
0198 
0199       if ((cnt = read(fd_, buf.data(), buf.size() - 1)) < 0) {
0200         perror("Read of Proc file failed:");
0201         return ProcInfo();
0202       }
0203 
0204       if (cnt > 0) {
0205         buf[cnt] = '\0';
0206 
0207         try {
0208           Fetcher fetcher(buf.data());
0209           fetcher >> pinfo.pid >> pinfo.comm >> pinfo.state >> pinfo.ppid >> pinfo.pgrp >> pinfo.session >> pinfo.tty >>
0210               pinfo.tpgid >> pinfo.flags >> pinfo.minflt >> pinfo.cminflt >> pinfo.majflt >> pinfo.cmajflt >>
0211               pinfo.utime >> pinfo.stime >> pinfo.cutime >> pinfo.cstime >> pinfo.priority >> pinfo.nice >>
0212               pinfo.num_threads >> pinfo.itrealvalue >> pinfo.starttime >> pinfo.vsize >> pinfo.rss >> pinfo.rlim >>
0213               pinfo.startcode >> pinfo.endcode >> pinfo.startstack >> pinfo.kstkesp >> pinfo.kstkeip >> pinfo.signal >>
0214               pinfo.blocked >> pinfo.sigignore >> pinfo.sigcatch >> pinfo.wchan;
0215         } catch (const std::exception& iE) {
0216           LogWarning("ProcInfoFetcher") << "Parsing of Prof file failed:" << iE.what() << std::endl;
0217           return ProcInfo();
0218         }
0219 
0220         // resident set size in pages
0221         pr_size = (double)pinfo.vsize;
0222         pr_rssize = (double)pinfo.rss;
0223 
0224         ret.vsize = pr_size / (1024.0 * 1024.0);
0225         ret.rss = (pr_rssize * pg_size_) / (1024.0 * 1024.0);
0226       }
0227 #else
0228       ret.vsize = 0;
0229       ret.rss = 0;
0230 #endif
0231       return ret;
0232     }
0233   }  // namespace service
0234 }  // namespace edm