From 0ccc9f3c530417019a2301585cec1ae307125a19 Mon Sep 17 00:00:00 2001 From: kzak <kzak@fedoraproject.org> Date: Wed, 9 Aug 2006 21:46:34 +0000 Subject: [PATCH] fix problem with threads --- lsof.spec | 9 ++- lsof_4.78C-threads.patch | 124 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 lsof_4.78C-threads.patch diff --git a/lsof.spec b/lsof.spec index bfcddc4..7ff0203 100644 --- a/lsof.spec +++ b/lsof.spec @@ -1,7 +1,7 @@ Summary: A utility which lists open files on a Linux/UNIX system. Name: lsof Version: 4.78 -Release: 1 +Release: 2 License: Free %define lsofrh lsof_4.78C-rh Group: Development/Debuggers @@ -12,6 +12,8 @@ BuildRoot: %{_tmppath}/%{name}-root BuildRequires: libselinux-devel +Patch1: lsof_4.78C-threads.patch + %description Lsof stands for LiSt Open Files, and it does just that: it lists information about files that are open by the processes running on a @@ -20,6 +22,8 @@ UNIX system. %prep %setup -q -n %{lsofrh} +%patch1 -p1 -b .kzak + %build LSOF_VSTR=2.6.16 LINUX_BASE=/proc ./Configure -n linux @@ -42,6 +46,9 @@ rm -rf ${RPM_BUILD_ROOT} %{_mandir}/man*/* %changelog +* Wed Aug 9 2006 Karel Zak <kzak@redhat.com> 4.78-2 +- fix #184338 - allow lsof access nptl threads + * Wed Jul 19 2006 Karel Zak <kzak@redhat.com> 4.78-1 - rebuild diff --git a/lsof_4.78C-threads.patch b/lsof_4.78C-threads.patch new file mode 100644 index 0000000..58284e2 --- /dev/null +++ b/lsof_4.78C-threads.patch @@ -0,0 +1,124 @@ +--- 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-09 23:25:14.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/<pid> is useless (zombie), we have to use /proc/<pid>/task/<tid> ++ * 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,60 @@ + (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; ++ ++ snpf(path, sizeof(path), "%s/%d/stat", PROCFS, pid); ++ if (!(f = fopen(path, "r"))) ++ return; ++ fscanf(f, "%d %*s %c", &_pid, &pstate); ++ fclose(f); ++ 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/<pid>/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/<pid>/task/<tid>/stat */ ++ snpf(path, sizeof(path), "%s/%d/task/%s/stat", PROCFS, pid, td->d_name); ++ if (!(f = fopen(path, "r"))) ++ continue; ++ fscanf(f, "%*d %*s %c", &pstate); ++ fclose(f); ++ if (pstate!='Z') { ++ re = 1; ++ *tid = strdup(td->d_name); ++ break; ++ } ++ } ++ closedir(tdp); ++ return re; ++} + + /* + * read_proc_stat() - read process status +@@ -931,12 +1001,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.