diff -up lsof_4.81-rh/dialects/linux/dproc.c.kzak lsof_4.81-rh/dialects/linux/dproc.c --- lsof_4.81-rh/dialects/linux/dproc.c.kzak 2008-10-21 18:17:25.000000000 +0200 +++ lsof_4.81-rh/dialects/linux/dproc.c 2008-12-02 10:54:54.000000000 +0100 @@ -89,7 +89,8 @@ _PROTOTYPE(static void process_proc_map, _PROTOTYPE(static int process_id,(char *idp, int idpl, char *cmd, UID_ARG uid, int pid, 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)); @@ -159,6 +160,7 @@ gather_proc_info() struct dirent *dp; struct stat sb; int lwp, n, nl, pgid, pid, ppid, rv, tx; + char *tid = NULL; static char *lwppath = (char *)NULL; static int lwppathl = 0; static char *path = (char *)NULL; @@ -252,6 +254,13 @@ gather_proc_info() while ((dp = readdir(ps))) { if (nm2id(dp->d_name, &pid, &n)) continue; + + tid = NULL; + if (get_other_thread(pid, &tid) < 0) + continue; + if (tid) + n += sizeof("task/") + strlen(tid); + /* * Build path to PID's directory. */ @@ -265,7 +274,14 @@ gather_proc_info() 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. @@ -1007,6 +1023,64 @@ process_id(idp, idpl, cmd, uid, pid, ppi return(0); } +/* 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; +} /* * process_proc_map() - process the memory map of a process @@ -1250,12 +1324,6 @@ read_id_stat(ty, p, id, cmd, ppid, pgid) return(1); } /* - * Convert the first field to an integer; its conversion must match the - * ID argument. - */ - if (!fp[0] || (atoi(fp[0]) != id)) - 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.