--- lsof_4.78C-rh/dialects/linux/dproc.c.kzak 2006-06-12 19:10:05.000000000 +0200 +++ lsof_4.78C-rh/dialects/linux/dproc.c 2006-08-10 00:14:23.000000000 +0200 @@ -69,7 +69,8 @@ _PROTOTYPE(static int read_proc_stat,(char *p, int pid, char **cmd, int *ppid, int *pgid)); _PROTOTYPE(static int statEx,(char *p, struct stat *s, int *ss)); - +_PROTOTYPE(static int get_other_thread,(int pid, char **tid)); + #if defined(HASSELINUX) _PROTOTYPE(static int cmp_cntx_eq,(char *pcntx, char *ucntx)); @@ -148,6 +149,7 @@ static char *path = (char *)NULL; static int pathl = 0; int pgid, pid, ppid; + char *tid = NULL; static char *pidpath = (char *)NULL; static MALLOC_S pidpathl = 0; static MALLOC_S pidx = 0; @@ -253,6 +255,13 @@ } if (f) continue; + + tid = NULL; + if (get_other_thread(pid, &tid) < 0) + continue; + if (tid) + n += sizeof("task/") + strlen(tid); + /* * Build path to PID's directory. */ @@ -266,7 +275,14 @@ Exit(1); } } - (void) snpf(pidpath + pidx, pidpathl - pidx, "%s/", dp->d_name); + if (tid) { + /* /proc/ is useless (zombie), we have to use /proc//task/ + * where is still running thread + */ + (void) snpf(pidpath + pidx, pidpathl - pidx, "%s/task/%s/", dp->d_name, tid); + free(tid); + } else + (void) snpf(pidpath + pidx, pidpathl - pidx, "%s/", dp->d_name); n += (pidx + 1); /* * Process the PID's stat info. @@ -897,6 +913,64 @@ (void) fclose(ms); } +/* fill tid if the initial thread is zombie, + * but other thread still alive + * + * returns -1=error, 0=nothing, 1=ok + */ +static int +get_other_thread(pid, tid) + int pid; + char **tid; +{ + char path[MAXPATHLEN]; + DIR *tdp; + struct dirent *td; + char pstate; + FILE *f; + int _pid; + int re = 0, x; + + snpf(path, sizeof(path), "%s/%d/stat", PROCFS, pid); + if (!(f = fopen(path, "r"))) + return -1; + x = fscanf(f, "%d %*s %c", &_pid, &pstate); + fclose(f); + if (x!=2) + return -1; + if (_pid != pid) + return -1; /* corrupted /proc? */ + if (pstate!='Z') + return 0; /* ignore normal proceses */ + + snpf(path, sizeof(path), "%s/%d/task", PROCFS, pid); + + /* open /proc//task */ + if (!(tdp = opendir(path))) + return 0; /* kernel < 2.6.x */ + + /* look for first alive thread */ + while ((td = readdir(tdp))) { + if (strcmp(td->d_name, ".")==0 || strcmp(td->d_name, "..")==0) + continue; + + /* /proc//task//stat */ + snpf(path, sizeof(path), "%s/%d/task/%s/stat", PROCFS, pid, td->d_name); + if (!(f = fopen(path, "r"))) + continue; + x = fscanf(f, "%*d %*s %c", &pstate); + fclose(f); + if (x!=1) + continue; + if (pstate!='Z') { + re = 1; + *tid = strdup(td->d_name); + break; + } + } + closedir(tdp); + return re; +} /* * read_proc_stat() - read process status @@ -931,12 +1005,6 @@ if ((nf = get_fields(buf, (char *)NULL, &fp, (int *)NULL, 0)) < 5) return(1); /* - * Convert the first field to an integer; its conversion must match the - * PID argument. - */ - if (atoi(fp[0]) != pid) - return(1); -/* * Get the command name from the second field. Strip a starting '(' and * an ending ')'. Allocate space to hold the result and return the space * pointer.