diff --git a/deviate.c b/deviate.c index c9ae3c0c..5f695729 100644 --- a/deviate.c +++ b/deviate.c @@ -455,6 +455,7 @@ calcdiff(struct tstat *devstat, const struct tstat *curstat, devstat->cpu.cgcpuweight = curstat->cpu.cgcpuweight; devstat->cpu.cgcpumax = curstat->cpu.cgcpumax; devstat->cpu.cgcpumaxr = curstat->cpu.cgcpumaxr; + devstat->cpu.nropen = curstat->cpu.nropen; if (curstat->cpu.wchan[0]) strcpy(devstat->cpu.wchan, curstat->cpu.wchan); diff --git a/json.c b/json.c index 2d4757b4..bdc942cd 100644 --- a/json.c +++ b/json.c @@ -1030,6 +1030,7 @@ static void json_print_PRC(char *hp, struct sstat *ss, struct tstat *ps, int nac "\"blkdelay\": %lld, " "\"nvcsw\": %llu, " "\"nivcsw\": %llu, " + "\"nropen\": %d, " "\"sleepavg\": %d}", ps->gen.pid, ps->cpu.utime, @@ -1043,6 +1044,7 @@ static void json_print_PRC(char *hp, struct sstat *ss, struct tstat *ps, int nac ps->cpu.blkdelay*1000/hertz, ps->cpu.nvcsw, ps->cpu.nivcsw, + ps->cpu.nropen, ps->cpu.sleepavg); } diff --git a/man/atop.1 b/man/atop.1 index c5a8ca2d..5368f852 100644 --- a/man/atop.1 +++ b/man/atop.1 @@ -1661,6 +1661,11 @@ Time that the process has been finished. If the process is still running, this field shows `active'. .PP .TP 9 +.B NROPEN +Current number of opened file descriptors (fds) for each process, at least 0. +As each thread has the same fds with its process, this filed shows `-`. +.PP +.TP 9 .B ENVID Virtual environment identified (OpenVZ only). .PP diff --git a/parseable.c b/parseable.c index 0cbca48b..fe9adcd7 100644 --- a/parseable.c +++ b/parseable.c @@ -785,7 +785,7 @@ print_PRC(char *hp, struct sstat *ss, struct tstat *ps, int nact) for (i=0; i < nact; i++, ps++) { printf("%s %d %s %c %u %lld %lld %d %d %d %d %d %d %d %c " - "%llu %s %llu %d %d %llu %llu\n", + "%llu %s %llu %d %d %d %llu %llu\n", hp, ps->gen.pid, spaceformat(ps->gen.name, namout), @@ -804,6 +804,7 @@ print_PRC(char *hp, struct sstat *ss, struct tstat *ps, int nact) ps->cpu.rundelay, spaceformat(ps->cpu.wchan, wchanout), ps->cpu.blkdelay, + ps->cpu.nropen, cgroupv2max(ps->gen.isproc, ps->cpu.cgcpumax), cgroupv2max(ps->gen.isproc, ps->cpu.cgcpumaxr), ps->cpu.nvcsw, diff --git a/photoproc.c b/photoproc.c index 5219f80d..c4b01a74 100644 --- a/photoproc.c +++ b/photoproc.c @@ -63,6 +63,7 @@ static int proccont(struct tstat *); static void proccmd(struct tstat *); static void procsmaps(struct tstat *); static void procwchan(struct tstat *); +static void procfd(struct tstat *); static count_t procschedstat(struct tstat *); static int proccgroupv2(struct tstat *); static struct cgroupv2vals * @@ -218,6 +219,8 @@ photoproc(struct tstat *tasklist, int maxtask) if (getwchan) procwchan(curtask); + procfd(curtask); + // read network stats from netatop netatop_gettask(curtask->gen.tgid, 'g', curtask); @@ -981,6 +984,38 @@ procschedstat(struct tstat *curtask) return curtask->cpu.rundelay; } +/* +** get current number of opened file descriptors for process +** to monitor if fd leaks. +** Considering users may set the max number of open files to +** a very large number, we regard MAX_OPEN to be 10000. +*/ +#define MAX_OPEN 10000 + +static void +procfd(struct tstat *curtask) +{ + DIR *dirp; + struct dirent *dentry; + int fd_num = 0; + + if ( (dirp = opendir("fd")) ) + { + while ( (dentry = readdir(dirp)) ) + { + if ( isdigit(dentry->d_name[0]) ) + fd_num++; + + if ( fd_num >= MAX_OPEN ) + break; + } + + curtask->cpu.nropen = fd_num; + + closedir(dirp); + } +} + /* ** CGROUP V2 specific items */ diff --git a/photoproc.h b/photoproc.h index b20e2654..2815dedd 100644 --- a/photoproc.h +++ b/photoproc.h @@ -82,7 +82,8 @@ struct tstat { int cgcpuweight; /* cgroup cpu.weight */ int cgcpumax; /* cgroup cpu.max percentage */ int cgcpumaxr; /* restrictive percentage */ - int ifuture[3]; /* reserved for future use */ + int nropen; /* number of opened files */ + int ifuture[2]; /* reserved for future use */ char wchan[16]; /* wait channel string */ count_t rundelay; /* schedstat rundelay (nanosec) */ count_t blkdelay; /* blkio delay (ticks) */ diff --git a/showlinux.c b/showlinux.c index 3d0b0947..185b19c6 100644 --- a/showlinux.c +++ b/showlinux.c @@ -423,6 +423,7 @@ proc_printdef *allprocpdefs[]= &procprt_STTIME, &procprt_ENDATE, &procprt_ENTIME, + &procprt_NROPEN, &procprt_THR, &procprt_TRUN, &procprt_TSLPI, @@ -1300,7 +1301,7 @@ priphead(int curlist, int totlist, char *showtype, char *showorder, "RUID:8 RGID:8 EUID:5 EGID:4 " "SUID:3 SGID:2 FSUID:3 FSGID:2 " "STDATE:7 STTIME:7 ENDATE:5 ENTIME:5 " - "ST:6 EXC:6 S:6 SORTITEM:10 CMD:10", + "NROPEN:5 ST:6 EXC:6 S:6 SORTITEM:10 CMD:10", "built-in varprocs"); make_proc_prints(cmdprocs, MAXITEMS, diff --git a/showlinux.h b/showlinux.h index f275a82a..87294548 100644 --- a/showlinux.h +++ b/showlinux.h @@ -418,6 +418,7 @@ extern proc_printdef procprt_STDATE; extern proc_printdef procprt_STTIME; extern proc_printdef procprt_ENDATE; extern proc_printdef procprt_ENTIME; +extern proc_printdef procprt_NROPEN; extern proc_printdef procprt_THR; extern proc_printdef procprt_TRUN; extern proc_printdef procprt_TSLPI; diff --git a/showprocs.c b/showprocs.c index da88d171..72bbe804 100644 --- a/showprocs.c +++ b/showprocs.c @@ -115,6 +115,8 @@ char *procprt_ENDATE_a(struct tstat *, int, int); char *procprt_ENDATE_e(struct tstat *, int, int); char *procprt_ENTIME_a(struct tstat *, int, int); char *procprt_ENTIME_e(struct tstat *, int, int); +char *procprt_NROPEN_a(struct tstat *, int, int); +char *procprt_NROPEN_e(struct tstat *, int, int); char *procprt_THR_a(struct tstat *, int, int); char *procprt_THR_e(struct tstat *, int, int); char *procprt_TRUN_a(struct tstat *, int, int); @@ -1235,6 +1237,32 @@ proc_printdef procprt_ENTIME = { " ENTIME ", "ENTIME", procprt_ENTIME_a, procprt_ENTIME_e, 8 }; /***************************************************************/ char * +procprt_NROPEN_a(struct tstat *curstat, int avgval, int nsecs) +{ + static char buf[64]; + + if (curstat->gen.isproc) + sprintf(buf, "%*d", procprt_NROPEN.width, curstat->cpu.nropen); + else + sprintf(buf, "%*s", procprt_NROPEN.width, "-"); + + return buf; +} + +char * +procprt_NROPEN_e(struct tstat *curstat, int avgval, int nsecs) +{ + static char buf[64]; + + sprintf(buf, "%*s", procprt_NROPEN.width, "-"); + + return buf; +} + +proc_printdef procprt_NROPEN = + { " NROPEN", "NROPEN", procprt_NROPEN_a, procprt_NROPEN_e, 7 }; +/***************************************************************/ +char * procprt_THR_a(struct tstat *curstat, int avgval, int nsecs) { static char buf[15];