From: Michael Tremer Date: Fri, 16 Apr 2010 17:16:51 +0000 (+0200) Subject: lsof: Add thread patch. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=071e59e9c7b10aa8f670915646c380ff3fc5fadd;p=ipfire-3.x.git lsof: Add thread patch. This patch will lsof learn how to handle threads. --- diff --git a/pkgs/core/lsof/patches/lsof_4.81-threads.patch b/pkgs/core/lsof/patches/lsof_4.81-threads.patch new file mode 100644 index 000000000..399819fdd --- /dev/null +++ b/pkgs/core/lsof/patches/lsof_4.81-threads.patch @@ -0,0 +1,129 @@ +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.