Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:13:05

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