hce-node application  1.4.3
HCE Hierarchical Cluster Engine node application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
DRCEReadProcessData.cpp
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <errno.h>
4 #include <stdarg.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include <signal.h>
8 #include <fcntl.h>
9 #include <sys/dir.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 
13 #include "DRCEReadProcessData.hpp"
14 
16 //-----------------------------------------------------------------------------
17 static void *xcalloc(void *pointer, int size)
18 {
19  void * ret;
20  if (pointer)
21  free(pointer);
22  if (!(ret = calloc(1, size)))
23  {
24  fprintf(stderr, "xcalloc: allocation error, size = %d\n", size);
25  exit(1);
26  }
27  return ret;
28 }
29 //-----------------------------------------------------------------------------
30 static void *xmalloc(unsigned int size)
31 {
32  void *p;
33 
34  if (size == 0)
35  ++size;
36  p = malloc(size);
37  if (!p)
38  {
39  fprintf(stderr, "xmalloc: malloc(%u) failed", size);
40  exit(1);
41  }
42  return(p);
43 }
44 
45 static int task_dir_missing;
46 //-----------------------------------------------------------------------------
47 typedef struct status_table_struct
48 {
49  enum{SZ=10};/*
50  status_table_struct(const char* name_, unsigned char len_, void* addr_)
51  {
52  memset(&name, 0, SZ);
53  strcpy((char*)name, name_);
54  len = len_;
55  addr = addr_;
56  }
57  status_table_struct(void)
58  {
59  memset(&name, 0, SZ);
60  len = 0;
61  addr = NULL;
62  }
63  status_table_struct& operator=(const status_table_struct& rhs)
64  {
65  if (&rhs!=this)
66  {
67  memset(&name, 0, SZ);
68  strcpy((char*)name, (char*)(rhs.name));
69  len = rhs.len;
70  addr = rhs.addr;
71  }
72  return *this;
73  }*/
74 
75  unsigned char name[SZ]; // /proc/*/status field name
76  unsigned char len; // name length
77 // long offset; // jump address offset
78  void *addr;
80 
81 //#define F(x) {#x, sizeof(#x)-1, (long)(&&case_##x - &&base)},
82 #define F(x) {#x, sizeof(#x)-1, &&case_##x},
83 #define NUL {"", 0, 0},
84 
85 // Suggested method:
86 // Grep this file for "case_", then strip those down to the name.
87 // (leave the colon and newline) So "Pid:\n" and "Threads:\n"
88 // would be lines in the file. (no quote, no escape, etc.)
89 //
90 // Watch out for name size in the status_table_struct (grrr, expanding)
91 // and the number of entries (we mask with 63 for now). The table
92 // must be padded out to 64 entries, maybe 128 in the future.
93 
94 static void status2proc(char *S, proc_t *restrict P, int is_proc)
95 {
96  long Threads = 0;
97  long Tgid = 0;
98  long Pid = 0;
99 
100  static const unsigned char asso[] =
101  {
102  61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
103  61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
104  61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
105  61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
106  61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
107  61, 61, 61, 61, 61, 61, 61, 61, 15, 61,
108  61, 61, 61, 61, 61, 61, 30, 3, 5, 5,
109  61, 5, 61, 8, 61, 61, 3, 61, 10, 61,
110  6, 61, 13, 0, 30, 25, 0, 61, 61, 61,
111  61, 61, 61, 61, 61, 61, 61, 3, 61, 13,
112  0, 0, 61, 30, 61, 25, 61, 61, 61, 0,
113  61, 61, 61, 61, 5, 61, 0, 61, 61, 61,
114  0, 61, 61, 61, 61, 61, 61, 61
115  };
116 
117  static const status_table_struct table[] = {
118  F(VmStk)
119  NUL NUL
120  F(State)
121  NUL
122  F(VmExe)
123  F(ShdPnd)
124  NUL
125  F(VmData)
126  NUL
127  F(Name)
128  NUL NUL
129  F(VmRSS)
130  NUL NUL
131  F(VmLck)
132  NUL NUL NUL
133  F(Gid)
134  F(Pid)
135  NUL NUL NUL
136  F(VmSize)
137  NUL NUL
138  F(VmLib)
139  NUL NUL
140  F(PPid)
141  NUL
142  F(SigCgt)
143  NUL
144  F(Threads)
145  F(SigPnd)
146  NUL
147  F(SigIgn)
148  NUL
149  F(Uid)
151  NUL NUL NUL NUL NUL
152  F(Tgid)
153  NUL NUL NUL NUL
154  F(SigBlk)
155  NUL NUL NUL
156  };
157 
158 #undef F
159 #undef NUL
160 
161  P->vm_size = 0;
162  P->vm_lock = 0;
163  P->vm_rss = 0;
164  P->vm_data = 0;
165  P->vm_stack= 0;
166  P->vm_exe = 0;
167  P->vm_lib = 0;
168  P->nlwp = 0;
169  P->signal[0] = '\0'; // so we can detect it as missing for very old kernels
170 
171  goto base;
172 
173  for(;;)
174  {
175  char *colon;
176  status_table_struct entry;
177 
178  // advance to next line
179  S = strchr(S, '\n');
180  if(unlikely(!S))
181  break; // if no newline
182  S++;
183 
184  // examine a field name (hash and compare)
185  base:
186  if(unlikely(!*S))
187  break;
188  entry = table[63 & (asso[(unsigned char)S[3]] + asso[(unsigned char)S[2]] + asso[(unsigned char)S[0]])];
189  colon = strchr(S, ':');
190  if(unlikely(!colon)) break;
191  if(unlikely(colon[1]!='\t')) break;
192  if(unlikely(colon-S != entry.len)) continue;
193  if(unlikely(memcmp(entry.name,S,colon-S))) continue;
194 
195  S = colon+2; // past the '\t'
196 
197 // goto *(&&base + entry.offset);
198  goto *entry.addr;
199 
200  case_Name:
201  {
202  unsigned u = 0;
203  while(u < sizeof P->cmd - 1u)
204  {
205  int c = *S++;
206  if(unlikely(c=='\n'))
207  break;
208  if(unlikely(c=='\0'))
209  break; // should never happen
210  if(unlikely(c=='\\'))
211  {
212  c = *S++;
213  if(c=='\n')
214  break; // should never happen
215  if(!c)
216  break; // should never happen
217  if(c=='n')
218  c='\n'; // else we assume it is '\\'
219  }
220  P->cmd[u++] = c;
221  }
222  P->cmd[u] = '\0';
223  S--; // put back the '\n' or '\0'
224  continue;
225  }
226  case_ShdPnd:
227  memcpy(P->signal, S, 16);
228  P->signal[16] = '\0';
229  continue;
230  case_SigBlk:
231  memcpy(P->blocked, S, 16);
232  P->blocked[16] = '\0';
233  continue;
234  case_SigCgt:
235  memcpy(P->sigcatch, S, 16);
236  P->sigcatch[16] = '\0';
237  continue;
238  case_SigIgn:
239  memcpy(P->sigignore, S, 16);
240  P->sigignore[16] = '\0';
241  continue;
242  case_SigPnd:
243  memcpy(P->_sigpnd, S, 16);
244  P->_sigpnd[16] = '\0';
245  continue;
246 
247  case_State:
248  P->state = *S;
249  continue;
250  case_Tgid:
251  Tgid = strtol(S,&S,10);
252  continue;
253  case_Pid:
254  Pid = strtol(S,&S,10);
255  continue;
256  case_PPid:
257  P->ppid = strtol(S,&S,10);
258  continue;
259  case_Threads:
260  Threads = strtol(S,&S,10);
261  continue;
262  case_Uid:
263  P->ruid = strtol(S,&S,10);
264  P->euid = strtol(S,&S,10);
265  P->suid = strtol(S,&S,10);
266  P->fuid = strtol(S,&S,10);
267  continue;
268  case_Gid:
269  P->rgid = strtol(S,&S,10);
270  P->egid = strtol(S,&S,10);
271  P->sgid = strtol(S,&S,10);
272  P->fgid = strtol(S,&S,10);
273  continue;
274  case_VmData:
275  P->vm_data = strtol(S,&S,10);
276  continue;
277  case_VmExe:
278  P->vm_exe = strtol(S,&S,10);
279  continue;
280  case_VmLck:
281  P->vm_lock = strtol(S,&S,10);
282  continue;
283  case_VmLib:
284  P->vm_lib = strtol(S,&S,10);
285  continue;
286  case_VmRSS:
287  P->vm_rss = strtol(S,&S,10);
288  continue;
289  case_VmSize:
290  P->vm_size = strtol(S,&S,10);
291  continue;
292  case_VmStk:
293  P->vm_stack = strtol(S,&S,10);
294  continue;
295  }
296 
297  // recent kernels supply per-tgid pending signals
298  if(!is_proc || !P->signal[0])
299  {
300  memcpy(P->signal, P->_sigpnd, 16);
301  P->signal[16] = '\0';
302  }
303  // Linux 2.4.13-pre1 to max 2.4.xx have a useless "Tgid"
304  // that is not initialized for built-in kernel tasks.
305  // Only 2.6.0 and above have "Threads" (nlwp) info.
306  if(Threads)
307  {
308  P->nlwp = Threads;
309  P->tgid = Tgid; // the POSIX PID value
310  P->tid = Pid; // the thread ID
311  }
312  else
313  {
314  P->nlwp = 1;
315  P->tgid = Pid;
316  P->tid = Pid;
317  }
318 }
319 //-----------------------------------------------------------------------------
320 // Reads /proc/*/stat files, being careful not to trip over processes with names
321 static void stat2proc(const char* S, proc_t *restrict P)
322 {
323  unsigned num;
324  char* tmp;
325 
326  /* fill in default values for older kernels */
327  P->processor = 0;
328  P->rtprio = -1;
329  P->sched = -1;
330  P->nlwp = 0;
331 
332  S = strchr(S, '(') + 1;
333  tmp = strrchr((char*)S, ')');
334  num = tmp - S;
335  if(unlikely(num >= sizeof P->cmd)) num = sizeof P->cmd - 1;
336  memcpy(P->cmd, S, num);
337  P->cmd[num] = '\0';
338  S = tmp + 2; // skip ") "
339 
340  sscanf(S,
341  "%c "
342  "%10d %10d %10d %10d %10d "
343  "%20lu %20lu %20lu %20lu %20lu "
344  "%20llu %20llu %20llu %20llu " /* utime stime cutime cstime */
345  "%20lu %20lu "
346  "%10d "
347  "%10lu "
348  "%20llu " /* start_time */
349  "%20lu "
350  "%20ld "
351  "%20lu %20lu %20lu %20lu %20lu %20lu "
352  "%*s %*s %*s %*s " /* discard, no RT signals & Linux 2.1 used hex */
353  "%20lu "
354  "%10d %10d "
355  "%20lu %20lu",
356  &P->state,
357  &P->ppid, &P->pgrp, &P->session, &P->tty, &P->tpgid,
358  &P->flags, &P->min_flt, &P->cmin_flt, &P->maj_flt, &P->cmaj_flt,
359  &P->utime, &P->stime, &P->cutime, &P->cstime,
360  &P->priority, &P->nice,
361  &P->nlwp,
362  &P->alarm,
363  &P->start_time,
364  &P->vsize,
365  &P->rss,
366  &P->rss_rlim, &P->start_code, &P->end_code, &P->start_stack, &P->kstk_esp, &P->kstk_eip,
367 /* P->signal, P->blocked, P->sigignore, P->sigcatch, */ /* can't use */
368  &P->wchan,
369 /* -- Linux 2.0.35 ends here -- */
370  &P->exit_signal, &P->processor, /* 2.2.1 ends with "exit_signal" */
371 /* -- Linux 2.2.8 to 2.5.17 end here -- */
372  &P->rtprio, &P->sched /* both added to 2.5.18 */
373  );
374 
375  if(!P->nlwp)
376  {
377  P->nlwp = 1;
378  }
379 }
380 //-----------------------------------------------------------------------------
381 static void statm2proc(const char* s, proc_t *restrict P)
382 {
383  if (P)
384  {
385  sscanf(s, "%20ld %20ld %20ld %20ld %20ld %20ld %20ld", &P->size, &P->resident, &P->share, &P->trs, &P->lrs, &P->drs, &P->dt);
386  }
387 }
388 //-----------------------------------------------------------------------------
389 static int file2str(const char *directory, const char *what, char *ret, int cap)
390 {
391  static char filename[80];
392  int fd, num_read;
393 
394  sprintf(filename, "%s/%s", directory, what);
395  fd = open(filename, O_RDONLY, 0);
396  if(unlikely(fd==-1))
397  return -1;
398  num_read = read(fd, ret, cap - 1);
399  close(fd);
400  if(unlikely(num_read<=0))
401  return -1;
402  ret[num_read] = '\0';
403  return num_read;
404 }
405 
406 /* These are some nice GNU C expression subscope "inline" functions.
407  * The can be used with arbitrary types and evaluate their arguments
408  * exactly once.
409  */
410 
411 /* Test if item X of type T is present in the 0 terminated list L */
412 # define XinL(T, X, L) ( { \
413  T x = (X), *l = (L); \
414  while (*l && *l != x) l++; \
415  *l == x; \
416  } )
417 
418 /* Test if item X of type T is present in the list L of length N */
419 # define XinLN(T, X, L, N) ( { \
420  T x = (X), *l = (L); \
421  int i = 0, n = (N); \
422  while (i < n && l[i] != x) i++; \
423  i < n && l[i] == x; \
424  } )
425 
427 // This reads process info from /proc in the traditional way, for one process.
428 // The pid (tgid? tid?) is already in p, and a path to it in path, with some
429 // room to spare.
430 static proc_t* simple_readproc(PROCTAB *restrict const PT, proc_t *restrict const p)
431 {
432  static struct stat sb; // stat() buffer
433  static char sbuf[1024]; // buffer for stat,statm
434  char *restrict const path = PT->path;
435  unsigned flags = PT->flags;
436 
437  if (unlikely(stat(path, &sb) == -1)) /* no such dirent (anymore) */
438  goto next_proc;
439 
440  if ((flags & PROC_UID) && !XinLN(uid_t, sb.st_uid, PT->uids, PT->nuid))
441  goto next_proc; /* not one of the requested uids */
442 
443  p->euid = sb.st_uid; /* need a way to get real uid */
444  p->egid = sb.st_gid; /* need a way to get real gid */
445 
446  if (flags & PROC_FILLSTAT)
447  { /* read, parse /proc/#/stat */
448  if (unlikely( file2str(path, "stat", sbuf, sizeof sbuf) == -1 ))
449  goto next_proc; /* error reading /proc/#/stat */
450  stat2proc(sbuf, p); /* parse /proc/#/stat */
451  }
452 
453  if (unlikely(flags & PROC_FILLMEM))
454  { /* read, parse /proc/#/statm */
455  if (likely( file2str(path, "statm", sbuf, sizeof sbuf) != -1 ))
456  statm2proc(sbuf, p); /* ignore statm errors here */
457  } /* statm fields just zero */
458 
459  if (flags & PROC_FILLSTATUS)
460  { /* read, parse /proc/#/status */
461  if (likely( file2str(path, "status", sbuf, sizeof sbuf) != -1 ))
462  {
463  status2proc(sbuf, p, 1);
464  }
465  }
466 
467  // if multithreaded, some values are crap
468  if(p->nlwp > 1)
469  {
470  p->wchan = (long)~0ull;
471  }
472 
473  return p;
474 next_proc:
475  return NULL;
476 }
477 //-----------------------------------------------------------------------------
478 // This finds processes in /proc in the traditional way.
479 // Return non-zero on success.
480 static int simple_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p)
481 {
482  static struct direct *ent; /* dirent handle */
483  char *restrict const path = PT->path;
484  for (;;)
485  {
486  ent = readdir(PT->procfs);
487  if(unlikely(unlikely(!ent) || unlikely(!ent->d_name)))
488  return 0;
489  if(likely( likely(*ent->d_name > '0') && likely(*ent->d_name <= '9') ))
490  break;
491  }
492  p->tgid = strtoul(ent->d_name, NULL, 10);
493  p->tid = p->tgid;
494  memcpy(path, "/proc/", 6);
495  strcpy(path+6, ent->d_name); // trust /proc to not contain evil top-level entries
496  return 1;
497 }
498 
500 // This finds tasks in /proc/*/task/ in the traditional way.
501 // Return non-zero on success.
502 static int simple_nexttid(PROCTAB *restrict const PT, const proc_t *restrict const p, proc_t *restrict const t, char *restrict const path)
503 {
504  static struct direct *ent; /* dirent handle */
505  if(PT->taskdir_user != p->tgid)
506  {
507  if(PT->taskdir)
508  {
509  closedir(PT->taskdir);
510  }
511  // use "path" as some tmp space
512  snprintf(path, PROCPATHLEN, "/proc/%d/task", p->tgid);
513  PT->taskdir = opendir(path);
514  if(!PT->taskdir) return 0;
515  PT->taskdir_user = p->tgid;
516  }
517  for (;;)
518  {
519  ent = readdir(PT->taskdir);
520  if(unlikely(unlikely(!ent) || unlikely(!ent->d_name)))
521  return 0;
522  if(likely( likely(*ent->d_name > '0') && likely(*ent->d_name <= '9') ))
523  break;
524  }
525  t->tid = strtoul(ent->d_name, NULL, 10);
526  t->tgid = p->tgid;
527  t->ppid = p->ppid; // cover for kernel behavior? we want both actually...?
528  snprintf(path, PROCPATHLEN, "/proc/%d/task/%s", p->tgid, ent->d_name);
529  return 1;
530 }
531 //-----------------------------------------------------------------------------
532 // This "finds" processes in a list that was given to openproc().
533 // Return non-zero on success. (tgid was handy)
534 static int listed_nextpid(PROCTAB *restrict const PT, proc_t *restrict const p)
535 {
536  char *restrict const path = PT->path;
537  pid_t tgid = *(PT->pids)++;
538  if(likely( tgid ))
539  {
540  snprintf(path, PROCPATHLEN, "/proc/%d", tgid);
541  p->tgid = tgid;
542  p->tid = tgid; // they match for leaders
543  }
544  return tgid;
545 }
546 //-----------------------------------------------------------------------------
547 /* readproc: return a pointer to a proc_t filled with requested info about the
548  * next process available matching the restriction set. If no more such
549  * processes are available, return a null pointer (boolean false). Use the
550  * passed buffer instead of allocating space if it is non-NULL. */
551 
552 /* This is optimized so that if a PID list is given, only those files are
553  * searched for in /proc. If other lists are given in addition to the PID list,
554  * the same logic can follow through as for the no-PID list case. This is
555  * fairly complex, but it does try to not to do any unnecessary work.
556  */
557 static proc_t* readproc(PROCTAB *restrict const PT, proc_t *restrict p)
558 {
559  proc_t* ret;
560  proc_t* saved_p;
561 
562  PT->did_fake=0;
563  saved_p = p;
564  if(!p)
565  p = (proc_t*)xcalloc(p, sizeof *p); /* passed buf or alloced mem */
566 
567  for(;;)
568  {
569  // fills in the path, plus p->tid and p->tgid
570  if (unlikely(! PT->finder(PT,p) ))
571  goto out;
572 
573  // go read the process data
574  ret = PT->reader(PT,p);
575  if(ret)
576  return ret;
577  }
578 
579 out:
580  if(!saved_p)
581  free(p);
582  return NULL;
583 }
584 //-----------------------------------------------------------------------------
585 // initiate a process table scan
586 static PROCTAB* openproc(int flags, ...)
587 {
588  va_list ap;
589  struct stat sbuf;
590  static int did_stat;
591  PROCTAB* PT = (PROCTAB*)xmalloc(sizeof(PROCTAB));
592 
593  if(!did_stat)
594  {
595  task_dir_missing = stat("/proc/self/task", &sbuf);
596  did_stat = 1;
597  }
598  PT->taskdir = NULL;
599  PT->taskdir_user = -1;
600  PT->taskfinder = simple_nexttid;
601 
602  PT->reader = simple_readproc;
603  if (flags & PROC_PID)
604  {
605  PT->procfs = NULL;
606  PT->finder = listed_nextpid;
607  }
608  else
609  {
610  PT->procfs = opendir("/proc");
611  if(!PT->procfs) return NULL;
612  PT->finder = simple_nextpid;
613  }
614  PT->flags = flags;
615 
616  va_start(ap, flags); /* Init args list */
617  if (flags & PROC_PID)
618  PT->pids = va_arg(ap, pid_t*);
619  else if (flags & PROC_UID)
620  {
621  PT->uids = va_arg(ap, uid_t*);
622  PT->nuid = va_arg(ap, int);
623  }
624  va_end(ap); /* Clean up args list */
625 
626  return PT;
627 }
628 //-----------------------------------------------------------------------------
629 // terminate a process table scan
630 static void closeproc(PROCTAB* PT)
631 {
632  if (PT)
633  {
634  if (PT->procfs)
635  closedir(PT->procfs);
636  if (PT->taskdir)
637  closedir(PT->taskdir);
638  memset(PT,'#',sizeof(PROCTAB));
639  free(PT);
640  }
641 }
642 //-----------------------------------------------------------------------------
643 // deallocate the space allocated by readproc if the passed rbuf was NULL
644 static void freeproc(proc_t* p)
645 {
646  if (!p) /* in case p is NULL */
647  return;
648  /* ptrs are after strings to avoid copying memory when building them. */
649  /* so free is called on the address of the address of strvec[0]. */
650  if (p->cmdline)
651  free((void*)*p->cmdline);
652  if (p->environ)
653  free((void*)*p->environ);
654  free(p);
655 }
656 //-----------------------------------------------------------------------------
657 /* get_proc_stats - lookup a single tasks information and fill out a proc_t
658  *
659  * On failure, returns NULL. On success, returns 'p' and 'p' is a valid
660  * and filled out proc_t structure.
661  */
662 static proc_t* getProcStats(pid_t pid, proc_t* p)
663 {
664  static char path[PATH_MAX], sbuf[1024];
665  struct stat statbuf;
666 
667  sprintf(path, "/proc/%d", pid);
668  if (stat(path, &statbuf))
669  {
670 // printf("path: %s\n", path);
671 // perror("stat");
672  return NULL;
673  }
674 
675  p = (proc_t*)xcalloc(p, sizeof *p);
676 
677  if (file2str(path, "stat", sbuf, sizeof sbuf) >= 0)
678  stat2proc(sbuf, p); /* parse /proc/#/stat */
679  if (file2str(path, "statm", sbuf, sizeof sbuf) >= 0)
680  statm2proc(sbuf, p); /* ignore statm errors here */
681  if (file2str(path, "status", sbuf, sizeof sbuf) >= 0)
682  status2proc(sbuf, p, 0 /*FIXME*/);
683 
684  return p;
685 }
686 //-----------------------------------------------------------------------------
688 
689 #include <Poco/Logger.h>
690 #include "Poco/TemporaryFile.h"
691 #include <iostream>
692 
693 #include <sstream>
694 #include <fstream>
695 
696 namespace HCE
697 {
698 namespace drce
699 {
700 //-----------------------------------------------------------------------------
701 DRCEReadProcessData* DRCEReadProcessData::pHandler = nullptr;
702 Poco::Mutex DRCEReadProcessData::mutex;
703 //-----------------------------------------------------------------------------
705 {
706  Poco::Mutex::ScopedLock lock(mutex);
707  if(!pHandler)
709  return *pHandler;
710 }
711 //-----------------------------------------------------------------------------
713 {
714  Poco::Mutex::ScopedLock lock(mutex);
715  if(pHandler)
716  {
717  delete pHandler;
718  pHandler=nullptr;
719  }
720 }
721 //-----------------------------------------------------------------------------
722 std::vector<pid_t> DRCEReadProcessData::getAllProcessIds(pid_t pid)
723 {
724  std::vector<pid_t> processes;
725  HCE::drce::DRCEReadProcessData::getChildrenList(pid, processes);
726  processes.push_back(pid);
727  return processes;
728 }
729 //-----------------------------------------------------------------------------
730 void DRCEReadProcessData::getChildrenList(pid_t pid, std::vector<pid_t>& children)
731 {
732  std::vector<ProcessData> processes = DRCEReadProcessData::getProcessDataList();
733  for (size_t i=0;i<processes.size();++i)
734  {
735  if (processes[i].ppid == pid)
736  {
737  children.push_back(processes[i].pid);
738  DRCEReadProcessData::getChildrenList(processes[i].pid, children);
739  }
740  }
741 }
742 //-----------------------------------------------------------------------------
743 // cppcheck-suppress unusedFunction
744 std::vector<ProcessData> DRCEReadProcessData::getProcessDataList(void)
745 {
746  Poco::Mutex::ScopedLock lock(mutex);
747  std::vector<ProcessData> processes;
748 
750  if (proc)
751  {
752  proc_t* procInfo= nullptr;
753  while ((procInfo = readproc(proc, nullptr)) != nullptr)
754  {
755  ProcessData processData;
756  processData.pid = procInfo->tid;
757  processData.ppid = procInfo->ppid;
758  processData.vram = procInfo->vm_size*1024; // to bytes
759  processData.rram = procInfo->vm_rss*1024; // to bytes
760  processData.threads = procInfo->nlwp;
761  processData.utime = procInfo->utime;
762  processData.stime = procInfo->stime;
763  processData.cutime = procInfo->cutime;
764  processData.cstime = procInfo->cstime;
765  processData.cmd = procInfo->cmd;
766  processes.push_back(processData);
767  freeproc(procInfo);
768  }
769  }
770  closeproc(proc);
771 
772  return processes;
773 }
774 //-----------------------------------------------------------------------------
776 {
777  Poco::Mutex::ScopedLock lock(mutex);
778  ProcessData processData;
779 
781  if (proc)
782  {
783  proc_t* procInfo = nullptr;
784  procInfo = getProcStats(pid, procInfo);
785  if (procInfo)
786  {
787  processData.pid = procInfo->tid;
788  processData.ppid = procInfo->ppid;
789  processData.vram = procInfo->vm_size*1024; // to bytes
790  processData.rram = procInfo->vm_rss*1024; // to bytes
791  processData.threads = procInfo->nlwp;
792  processData.utime = procInfo->utime;
793  processData.stime = procInfo->stime;
794  processData.cutime = procInfo->cutime;
795  processData.cstime = procInfo->cstime;
796  processData.cmd = procInfo->cmd;
797  freeproc(procInfo);
798  }
799  }
800  closeproc(proc);
801 
802  return processData;
803 }
804 //-----------------------------------------------------------------------------
805 void DRCEReadProcessData::getProcessAndThreads(unsigned int& processCount, unsigned int& threadsCount)
806 {
807  Poco::Mutex::ScopedLock lock(mutex);
808  processCount = 0;
809  threadsCount = 0;
810 
812  if (proc)
813  {
814  proc_t* procInfo= nullptr;
815  while ((procInfo = readproc(proc, nullptr)) != nullptr)
816  {
817  ++processCount;
818  threadsCount += static_cast<unsigned int>(procInfo->nlwp);
819  freeproc(procInfo);
820  }
821  }
822  closeproc(proc);
823 }
824 //-----------------------------------------------------------------------------
825 //-----------------------------------------------------------------------------
826 } // end namespace drce
827 } // end namespace HCE
828 
829 
830