import source from 4.82
[external/lsof.git] / packaging / lsof_4.81-threads.patch
1 diff -up lsof_4.81-rh/dialects/linux/dproc.c.kzak lsof_4.81-rh/dialects/linux/dproc.c
2 --- lsof_4.81-rh/dialects/linux/dproc.c.kzak    2008-10-21 18:17:25.000000000 +0200
3 +++ lsof_4.81-rh/dialects/linux/dproc.c 2008-12-02 10:54:54.000000000 +0100
4 @@ -89,7 +89,8 @@ _PROTOTYPE(static void process_proc_map,
5  _PROTOTYPE(static int process_id,(char *idp, int idpl, char *cmd, UID_ARG uid,
6                                   int pid, int ppid, int pgid));
7  _PROTOTYPE(static int statEx,(char *p, struct stat *s, int *ss));
8
9 +_PROTOTYPE(static int get_other_thread,(int pid, char **tid));
10 +
11  
12  #if    defined(HASSELINUX)
13  _PROTOTYPE(static int cmp_cntx_eq,(char *pcntx, char *ucntx));
14 @@ -159,6 +160,7 @@ gather_proc_info()
15         struct dirent *dp;
16         struct stat sb;
17         int lwp, n, nl, pgid, pid, ppid, rv, tx;
18 +       char *tid = NULL;
19         static char *lwppath = (char *)NULL;
20         static int lwppathl = 0;
21         static char *path = (char *)NULL;
22 @@ -252,6 +254,13 @@ gather_proc_info()
23         while ((dp = readdir(ps))) {
24             if (nm2id(dp->d_name, &pid, &n))
25                 continue;
26 +
27 +           tid = NULL;
28 +           if (get_other_thread(pid, &tid) < 0)
29 +               continue;
30 +           if (tid)
31 +               n += sizeof("task/") + strlen(tid);
32 +
33         /*
34          * Build path to PID's directory.
35          */
36 @@ -265,7 +274,14 @@ gather_proc_info()
37                     Exit(1);
38                 }
39             }
40 -           (void) snpf(pidpath + pidx, pidpathl - pidx, "%s/", dp->d_name);
41 +           if (tid) {
42 +               /* /proc/<pid> is useless (zombie), we have to use /proc/<pid>/task/<tid>
43 +                * where is still running thread
44 +                */
45 +               (void) snpf(pidpath + pidx, pidpathl - pidx, "%s/task/%s/", dp->d_name, tid);
46 +               free(tid);
47 +           } else
48 +               (void) snpf(pidpath + pidx, pidpathl - pidx, "%s/", dp->d_name);
49             n += (pidx + 1);
50         /*
51          * Process the PID's stat info.
52 @@ -1007,6 +1023,64 @@ process_id(idp, idpl, cmd, uid, pid, ppi
53         return(0);
54  }
55  
56 +/* fill tid if the initial thread is zombie,
57 + * but other thread still alive
58 + *
59 + * returns -1=error, 0=nothing, 1=ok
60 + */
61 +static int
62 +get_other_thread(pid, tid)
63 +       int pid;
64 +       char **tid;
65 +{
66 +       char path[MAXPATHLEN];
67 +       DIR *tdp;
68 +       struct dirent *td;
69 +       char pstate;
70 +       FILE *f;
71 +       int _pid;
72 +       int re = 0, x;
73 +
74 +       snpf(path, sizeof(path), "%s/%d/stat", PROCFS, pid);
75 +       if (!(f = fopen(path, "r")))
76 +               return -1;
77 +       x = fscanf(f, "%d %*s %c", &_pid, &pstate);
78 +       fclose(f);
79 +       if (x!=2)
80 +               return -1;
81 +       if (_pid != pid)
82 +               return -1;              /* corrupted /proc? */
83 +       if (pstate!='Z')
84 +               return 0;               /* ignore normal proceses */
85 +
86 +       snpf(path, sizeof(path), "%s/%d/task", PROCFS, pid);
87 +
88 +       /* open /proc/<pid>/task */
89 +       if (!(tdp = opendir(path)))
90 +               return 0;               /* kernel < 2.6.x */
91 +
92 +       /* look for first alive thread */
93 +       while ((td = readdir(tdp))) {
94 +               if (strcmp(td->d_name, ".")==0 || strcmp(td->d_name, "..")==0)
95 +                       continue;
96 +
97 +               /* /proc/<pid>/task/<tid>/stat */
98 +               snpf(path, sizeof(path), "%s/%d/task/%s/stat", PROCFS, pid, td->d_name);
99 +               if (!(f = fopen(path, "r")))
100 +                       continue;
101 +               x = fscanf(f, "%*d %*s %c", &pstate);
102 +               fclose(f);
103 +               if (x!=1)
104 +                       continue;
105 +               if (pstate!='Z') {
106 +                       re = 1;
107 +                       *tid = strdup(td->d_name);
108 +                       break;
109 +               }
110 +       }
111 +       closedir(tdp);
112 +       return re;
113 +}
114  
115  /*
116   * process_proc_map() - process the memory map of a process
117 @@ -1250,12 +1324,6 @@ read_id_stat(ty, p, id, cmd, ppid, pgid)
118             return(1);
119         }
120  /*
121 - * Convert the first field to an integer; its conversion must match the
122 - * ID argument.
123 - */
124 -       if (!fp[0] || (atoi(fp[0]) != id))
125 -           return(1);
126 -/*
127   * Get the command name from the second field.  Strip a starting '(' and
128   * an ending ')'.  Allocate space to hold the result and return the space
129   * pointer.