bool DirectorCore::buildProcessMap(void) noexcept { // search existing processes for those we should be managing (not 100% foolproof) process_state_t state; std::set<pid_t> pidlist; const pid_t thispid = posix::getpid(); if(proclist(pidlist) == posix::success_response) { for(pid_t pid : pidlist) { posix::memset(reinterpret_cast<void*>(&state), 0, sizeof(state)); if(procstat(pid, state) && // if get process state works AND (!state.parent_process_id || state.parent_process_id == thispid)) // process has unknown parent process OR director is the parent process for(const std::string& config : getConfigList()) // try each config if(getConfigValue(config, "/Process/Executable") == state.executable) // if the executable matches { m_process_map[config]->add(thispid, pid); // claim this as a managed process posix::memset(reinterpret_cast<void*>(&state), 0, sizeof(state)); // wipe process state for safety for(pid_t childpid : pidlist) if(procstat(childpid, state) && // if get process state works AND state.parent_process_id == pid) // process is a child of this parent pid m_process_map[config]->add(pid, childpid); // claim this as a managed process } } return true; } return false; }
bool ProxyHost(EDF *pEDF) { debug(DEBUGLEVEL_INFO, "ProxyHost entry\n"); #ifndef FreeBSD int iPID = 0, iPPID = 0, iSession = 0, iPrevSession = 0; struct utmp *pEntry = NULL; // printf("tty %s\n", ttyname(0)); // szHost[0] = '\0'; // if(utmpscan(-1, szHost) == false) pEntry = utmpscan(-1); if(pEntry == NULL) { // Couldn't find this process debug(DEBUGLEVEL_ERR, "ProxyHost exit false, utmpscan failed\n"); return false; } debug(DEBUGLEVEL_INFO, "ProxyHost host '%s'\n", pEntry->ut_host); if(strchr(pEntry->ut_host, ':') != NULL) { debug(DEBUGLEVEL_INFO, "ProxyHost parent check\n"); iPID = getppid(); while(iPID != 0 && procstat(iPID, &iPPID, &iSession) == true) { debug(DEBUGLEVEL_INFO, "ProxyHost %d (parent %d, session %d)\n", iPID, iPPID, iSession); if(iPrevSession == iSession) { // szHost[0] = '\0'; pEntry = utmpscan(iSession); ProxyHostEntry(pEDF, pEntry); iPID = 0; } else { iPrevSession = iSession; iPID = iPPID; } } } else { ProxyHostEntry(pEDF, pEntry); } #endif debug(DEBUGLEVEL_INFO, "ProxyHost exit true\n"); return true; }
static void register_child(pid_t parent, pid_t child) { embht_table *ht = get_pid_table(parent, 1); embht_entry *ent; struct procstat pstb; assert(ht); if ( procstat(child, &pstb) != 0 ) { fprintf(stderr, "Orphand: procstat(%d) failed with %d,%d\n", child, pstb.lib_error, pstb.sys_error); return; } ent = embht_fetchi(ht, child, 1); *(uint64_t*)(ent->u_value.value) = pstb.pst_starttime; }
int photoproc(struct tstat *tasklist, int maxtask) { static int firstcall = 1; static unsigned long long bootepoch; register struct tstat *curtask; FILE *fp; DIR *dirp; struct dirent *entp; char origdir[1024]; int tval=0; /* ** one-time initialization stuff */ if (firstcall) { /* ** check if this kernel offers io-statistics per task */ regainrootprivs(); if ( (fp = fopen("/proc/1/io", "r")) ) { supportflags |= IOSTAT; fclose(fp); } if (! droprootprivs()) cleanstop(42); /* ** find epoch time of boot moment */ bootepoch = getboot(); firstcall = 0; } /* ** probe if the netatop module and (optionally) the ** netatopd daemon are active */ regainrootprivs(); netatop_probe(); if (! droprootprivs()) cleanstop(42); /* ** read all subdirectory-names below the /proc directory */ if ( getcwd(origdir, sizeof origdir) == NULL) cleanstop(53); if ( chdir("/proc") == -1) cleanstop(53); dirp = opendir("."); while ( (entp = readdir(dirp)) && tval < maxtask ) { /* ** skip non-numerical names */ if (!isdigit(entp->d_name[0])) continue; /* ** change to the process' subdirectory */ if ( chdir(entp->d_name) != 0 ) continue; /* ** gather process-level information */ curtask = tasklist+tval; if ( !procstat(curtask, bootepoch, 1)) /* from /proc/pid/stat */ { if ( chdir("..") == -1); continue; } if ( !procstatus(curtask) ) /* from /proc/pid/status */ { if ( chdir("..") == -1); continue; } if ( !procio(curtask) ) /* from /proc/pid/io */ { if ( chdir("..") == -1); continue; } proccmd(curtask); /* from /proc/pid/cmdline */ // read network stats from netatop netatop_gettask(curtask->gen.tgid, 'g', curtask); tval++; /* increment for process-level info */ /* ** if needed (when number of threads is larger than 0): ** read and fill new entries with thread-level info */ if (curtask->gen.nthr > 1) { DIR *dirtask; struct dirent *tent; curtask->gen.nthrrun = 0; curtask->gen.nthrslpi = 0; curtask->gen.nthrslpu = 0; /* ** open underlying task directory */ if ( chdir("task") == 0 ) { dirtask = opendir("."); while ((tent=readdir(dirtask)) && tval<maxtask) { struct tstat *curthr = tasklist+tval; /* ** change to the thread's subdirectory */ if ( tent->d_name[0] == '.' || chdir(tent->d_name) != 0 ) continue; if ( !procstat(curthr, bootepoch, 0)) { if ( chdir("..") == -1); continue; } if ( !procstatus(curthr) ) { if ( chdir("..") == -1); continue; } if ( !procio(curthr) ) { if ( chdir("..") == -1); continue; } switch (curthr->gen.state) { case 'R': curtask->gen.nthrrun += 1; break; case 'S': curtask->gen.nthrslpi += 1; break; case 'D': curtask->gen.nthrslpu += 1; break; } curthr->gen.nthr = 1; // read network stats from netatop netatop_gettask(curthr->gen.pid, 't', curthr); // all stats read now tval++; /* increment thread-level */ if ( chdir("..") == -1); /* thread */ } closedir(dirtask); if ( chdir("..") == -1); /* leave task */ } } if ( chdir("..") == -1); /* leave process-level directry */ } closedir(dirp); if ( chdir(origdir) == -1) cleanstop(53); return tval; }
static void sweep(void) { embht_iterator parents_iter; embht_iterinit(Server.ht, &parents_iter); while (embht_iternext(&parents_iter)) { embht_table *children_ht; embht_entry *children_hb; embht_iterator child_iter; struct procstat pstb; children_hb = embht_itercur(&parents_iter); pid_t parent_pid = children_hb->key.u_kdata.kd32; children_ht = children_hb->u_value.ptr; DEBUG("Checking children of %d", parent_pid); if (parent_pid < 1) { ERROR("Found a parent with a PID < 1"); goto GT_CLEAN_PARENT; } if (kill(parent_pid, 0) == 0) { DEBUG("Parent still alive"); continue; } else { int old_errno = errno; if (old_errno != ESRCH) { WARN("Couldn't determine whether %d is alive: %s", parent_pid, strerror(old_errno)); goto GT_CLEAN_PARENT; } } embht_iterinit(children_ht, &child_iter); while (embht_iternext(&child_iter)) { uint64_t child_start = *(uint64_t*)(embht_itercur(&child_iter)->u_value.value); pid_t child_pid = embht_itercur(&child_iter)->key.u_kdata.kd32; if (child_pid < 1) { continue; } if (procstat(child_pid, &pstb) != 0) { fprintf(stderr, "procstat(%d) (%d,%d)\n", child_pid, pstb.lib_error, pstb.sys_error); continue; } if (pstb.pst_starttime != child_start) { INFO("PID %d found but start times differ", child_pid); continue; } INFO("Dead parent %d: Killing %d", parent_pid, child_pid); kill(child_pid, Server.default_signum); } GT_CLEAN_PARENT: if (children_ht) { embht_destroy(children_ht); } embht_iterdel(&parents_iter); } }
int main(int argc, char *argv[]) { int ch, interval, tmp; int i; struct kinfo_proc *p; struct procstat *prstat, *cprstat; long l; pid_t pid; char *dummy; char *nlistf, *memf; const char *xocontainer; int cnt; interval = 0; memf = nlistf = NULL; argc = xo_parse_args(argc, argv); xocontainer = "basic"; while ((ch = getopt(argc, argv, "CHN:M:abcefijklhrsStvw:x")) != -1) { switch (ch) { case 'C': Cflag++; break; case 'H': Hflag++; break; case 'M': memf = optarg; break; case 'N': nlistf = optarg; break; case 'S': Sflag++; xocontainer = "cs"; break; case 'a': aflag++; break; case 'b': bflag++; xocontainer = "binary"; break; case 'c': cflag++; xocontainer = "arguments"; break; case 'e': eflag++; xocontainer = "environment"; break; case 'f': fflag++; xocontainer = "files"; break; case 'i': iflag++; xocontainer = "signals"; break; case 'j': jflag++; xocontainer = "thread_signals"; break; case 'k': kflag++; xocontainer = "kstack"; break; case 'l': lflag++; xocontainer = "rlimit"; break; case 'n': nflag++; break; case 'h': hflag++; break; case 'r': rflag++; xocontainer = "rusage"; break; case 's': sflag++; xocontainer = "credentials"; break; case 't': tflag++; xocontainer = "threads"; break; case 'v': vflag++; xocontainer = "vm"; break; case 'w': l = strtol(optarg, &dummy, 10); if (*dummy != '\0') usage(); if (l < 1 || l > INT_MAX) usage(); interval = l; break; case 'x': xflag++; xocontainer = "auxv"; break; case '?': default: usage(); } } argc -= optind; argv += optind; /* We require that either 0 or 1 mode flags be set. */ tmp = bflag + cflag + eflag + fflag + iflag + jflag + (kflag ? 1 : 0) + lflag + rflag + sflag + tflag + vflag + xflag + Sflag; if (!(tmp == 0 || tmp == 1)) usage(); /* We allow -k to be specified up to twice, but not more. */ if (kflag > 2) usage(); /* Must specify either the -a flag or a list of pids. */ if (!(aflag == 1 && argc == 0) && !(aflag == 0 && argc > 0)) usage(); /* Only allow -C with -f. */ if (Cflag && !fflag) usage(); if (memf != NULL) prstat = procstat_open_kvm(nlistf, memf); else prstat = procstat_open_sysctl(); if (prstat == NULL) xo_errx(1, "procstat_open()"); do { xo_set_version(PROCSTAT_XO_VERSION); xo_open_container("procstat"); xo_open_container(xocontainer); if (aflag) { p = procstat_getprocs(prstat, KERN_PROC_PROC, 0, &cnt); if (p == NULL) xo_errx(1, "procstat_getprocs()"); kinfo_proc_sort(p, cnt); for (i = 0; i < cnt; i++) { procstat(prstat, &p[i]); /* Suppress header after first process. */ hflag = 1; xo_flush(); } procstat_freeprocs(prstat, p); } for (i = 0; i < argc; i++) { l = strtol(argv[i], &dummy, 10); if (*dummy == '\0') { if (l < 0) usage(); pid = l; p = procstat_getprocs(prstat, KERN_PROC_PID, pid, &cnt); if (p == NULL) xo_errx(1, "procstat_getprocs()"); if (cnt != 0) procstat(prstat, p); procstat_freeprocs(prstat, p); } else { cprstat = procstat_open_core(argv[i]); if (cprstat == NULL) { warnx("procstat_open()"); continue; } p = procstat_getprocs(cprstat, KERN_PROC_PID, -1, &cnt); if (p == NULL) xo_errx(1, "procstat_getprocs()"); if (cnt != 0) procstat(cprstat, p); procstat_freeprocs(cprstat, p); procstat_close(cprstat); } /* Suppress header after first process. */ hflag = 1; } xo_close_container(xocontainer); xo_close_container("procstat"); xo_finish(); if (interval) sleep(interval); } while (interval); procstat_close(prstat); exit(0); }
int main(int argc, char *argv[]) { int ch, interval, tmp; int i; struct kinfo_proc *p; struct procstat *prstat, *cprstat; long l; pid_t pid; char *dummy; char *nlistf, *memf; int cnt; interval = 0; memf = nlistf = NULL; while ((ch = getopt(argc, argv, "CHLM:N:ORSXabcefijklhrstvw:x")) != -1) { switch (ch) { case 'C': Cflag++; break; case 'L': Lflag++; break; case 'H': Hflag++; break; case 'M': memf = optarg; break; case 'N': nlistf = optarg; break; case 'O': Oflag++; break; case 'R': Rflag++; break; case 'S': Sflag++; break; case 'X': Xflag++; break; case 'a': aflag++; break; case 'b': bflag++; break; case 'c': cflag++; break; case 'e': eflag++; break; case 'f': fflag++; break; case 'i': iflag++; break; case 'j': jflag++; break; case 'k': kflag++; break; case 'l': lflag++; break; case 'n': nflag++; break; case 'h': hflag++; break; case 'r': rflag++; break; case 's': sflag++; break; case 't': tflag++; break; case 'v': vflag++; break; case 'w': l = strtol(optarg, &dummy, 10); if (*dummy != '\0') usage(); if (l < 1 || l > INT_MAX) usage(); interval = l; break; case 'x': xflag++; break; case '?': default: usage(); } } argc -= optind; argv += optind; /* We require that either 0 or 1 mode flags be set. */ tmp = Lflag + Oflag + Rflag + Sflag + bflag + cflag + eflag + fflag + iflag + jflag + (kflag ? 1 : 0) + lflag + rflag + sflag + tflag + vflag + xflag; if (!(tmp == 0 || tmp == 1)) usage(); /* We allow -k to be specified up to twice, but not more. */ if (kflag > 2) usage(); /* Must specify either the -a flag or a list of pids. */ if (!(aflag == 1 && argc == 0) && !(aflag == 0 && argc > 0)) usage(); /* Only allow -C with -f. */ if (Cflag && !fflag) usage(); /* Only allow -X with -S and -R. */ if (Xflag && !(Sflag || Rflag)) usage(); if (memf != NULL) prstat = procstat_open_kvm(nlistf, memf); else prstat = procstat_open_sysctl(); if (prstat == NULL) errx(1, "procstat_open()"); do { if (aflag) { p = procstat_getprocs(prstat, KERN_PROC_PROC, 0, &cnt); if (p == NULL) errx(1, "procstat_getprocs()"); kinfo_proc_sort(p, cnt); for (i = 0; i < cnt; i++) { procstat(prstat, &p[i]); /* Suppress header after first process. */ hflag = 1; } procstat_freeprocs(prstat, p); } for (i = 0; i < argc; i++) { l = strtol(argv[i], &dummy, 10); if (*dummy == '\0') { if (l < 0) usage(); pid = l; p = procstat_getprocs(prstat, KERN_PROC_PID, pid, &cnt); if (p == NULL) errx(1, "procstat_getprocs()"); if (cnt != 0) procstat(prstat, p); procstat_freeprocs(prstat, p); } else { cprstat = procstat_open_core(argv[i]); if (cprstat == NULL) { warnx("procstat_open()"); continue; } p = procstat_getprocs(cprstat, KERN_PROC_PID, -1, &cnt); if (p == NULL) errx(1, "procstat_getprocs()"); if (cnt != 0) procstat(cprstat, p); procstat_freeprocs(cprstat, p); procstat_close(cprstat); } /* Suppress header after first process. */ hflag = 1; } if (interval) sleep(interval); } while (interval); procstat_close(prstat); exit(0); }