a7e8a17b77
- lsof_4.80-threads.patch - rebased
130 lines
3.5 KiB
Diff
130 lines
3.5 KiB
Diff
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/<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.
|
|
@@ -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/<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;
|
|
+ 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.
|