summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS1
-rw-r--r--proc/module.mk9
-rw-r--r--proc/procps.h5
-rw-r--r--proc/readproc.c336
-rw-r--r--proc/readproc.h1
5 files changed, 255 insertions, 97 deletions
diff --git a/NEWS b/NEWS
index e123cf4..5787a25 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,6 @@
procps-3.1.5 --> procps-3.1.6
+handle the 2.5.61 kernel
top: memory leak fixed
ps: new --ppid option selects by PPID
watch: new --no-title option #179862
diff --git a/proc/module.mk b/proc/module.mk
index e0f1bd7..de0399b 100644
--- a/proc/module.mk
+++ b/proc/module.mk
@@ -14,19 +14,22 @@ LIBOBJ := $(LIBSRC:.c=.o)
#ALL += proc/lib$(NAME).a
#INSTALL += $(usr/lib)/lib$(NAME).a # plus $(usr/include)$(NAME) gunk
+FPIC := -fpic
+
ifeq ($(SHARED),1)
ALL += proc/$(SONAME)
INSTALL += $(lib)/$(SONAME)
-FPIC := -fpic
+LIBFLAGS := -DSHARED=1 $(FPIC)
LIBPROC := proc/$(SONAME)
else
ALL += proc/lib$(NAME).a
+LIBFLAGS := -DSHARED=0
LIBPROC := proc/lib$(NAME).a
endif
# Separate rule for this directory, to use -fpic or -fPIC
$(filter-out proc/version.o,$(LIBOBJ)): proc/%.o: proc/%.c
- $(CC) -c $(CFLAGS) $(FPIC) $< -o $@
+ $(CC) -c $(CFLAGS) $(LIBFLAGS) $< -o $@
LIB_X := COPYING module.mk library.map
TARFILES += $(LIBSRC) $(LIBHDR) $(addprefix proc/,$(LIB_X))
@@ -71,4 +74,4 @@ $(lib)/$(SONAME) : proc/$(SONAME)
proc/version.o: proc/version.c proc/version.h
- $(CC) $(CFLAGS) $(FPIC) -DVERSION=\"$(VERSION)\" -DSUBVERSION=\"$(SUBVERSION)\" -DMINORVERSION=\"$(MINORVERSION)\" -c -o $@ $<
+ $(CC) $(CFLAGS) $(LIBFLAGS) -DVERSION=\"$(VERSION)\" -DSUBVERSION=\"$(SUBVERSION)\" -DMINORVERSION=\"$(MINORVERSION)\" -c -o $@ $<
diff --git a/proc/procps.h b/proc/procps.h
index 95134a6..5909c20 100644
--- a/proc/procps.h
+++ b/proc/procps.h
@@ -64,6 +64,11 @@
#define expected(x,y) (x)
#endif
+#if SHARED==1 && (__GNUC__ > 2 || __GNUC_MINOR__ >= 96)
+#define LABEL_OFFSET
+#endif
+
+
// marks old junk, to warn non-procps library users
#if ( __GNUC__ == 3 && __GNUC_MINOR__ > 0 ) || __GNUC__ > 3
#define OBSOLETE __attribute__((deprecated))
diff --git a/proc/readproc.c b/proc/readproc.c
index f71ce16..941d7a8 100644
--- a/proc/readproc.c
+++ b/proc/readproc.c
@@ -31,6 +31,15 @@
#include <fs_secure.h>
#endif
+#ifdef PROF
+extern void __cyg_profile_func_enter(void*,void*);
+#define ENTER(x) __cyg_profile_func_enter((void*)x,(void*)x)
+#define LEAVE(x) __cyg_profile_func_exit((void*)x,(void*)x)
+#else
+#define ENTER(x)
+#define LEAVE(x)
+#endif
+
/* initiate a process table scan
*/
PROCTAB* openproc(int flags, ...) {
@@ -77,103 +86,237 @@ void freeproc(proc_t* p) {
}
-// 2.5.xx looks like:
-//
-// "State:\t%s\n"
-// "Tgid:\t%d\n"
-// "Pid:\t%d\n"
-// "PPid:\t%d\n"
-// "TracerPid:\t%d\n"
-
-static void status2proc(const char *S, proc_t *restrict P){
- char* tmp;
- unsigned i;
-
- // The cmd is escaped, with \\ and \n for backslash and newline.
- // It certainly may contain "VmSize:" and similar crap.
- if(unlikely(strncmp("Name:\t",S,6))) fprintf(stderr, "Internal error!\n");
- S += 6;
- i = 0;
- while(i < sizeof P->cmd - 1){
- int c = *S++;
- if(unlikely(c=='\n')) break;
- if(unlikely(c=='\0')) return; // should never happen
- if(unlikely(c=='\\')){
- c = *S++;
- if(c=='\n') break; // should never happen
- if(!c) break; // should never happen
- if(c=='n') c='\n'; // else we assume it is '\\'
- }
- P->cmd[i++] = c;
- }
- P->cmd[i] = '\0';
-
- tmp = strstr (S,"State:\t");
- if(likely(tmp)) P->state = tmp[7];
- else fprintf(stderr, "Internal error!\n");
-
- tmp = strstr (S,"PPid:");
- if(likely(tmp)) sscanf (tmp,
- "PPid:\t%d\n",
- &P->ppid
- );
- else fprintf(stderr, "Internal error!\n");
-
- tmp = strstr (S,"Uid:");
- if(likely(tmp)) sscanf (tmp,
- "Uid:\t%d\t%d\t%d\t%d",
- &P->ruid, &P->euid, &P->suid, &P->fuid
- );
- else fprintf(stderr, "Internal error!\n");
+///////////////////////////////////////////////////////////////////////////
- tmp = strstr (S,"Gid:");
- if(likely(tmp)) sscanf (tmp,
- "Gid:\t%d\t%d\t%d\t%d",
- &P->rgid, &P->egid, &P->sgid, &P->fgid
- );
- else fprintf(stderr, "Internal error!\n");
-
- tmp = strstr (S,"VmSize:");
- if(likely(tmp)) sscanf (tmp,
- "VmSize: %lu kB\n"
- "VmLck: %lu kB\n"
- "VmRSS: %lu kB\n"
- "VmData: %lu kB\n"
- "VmStk: %lu kB\n"
- "VmExe: %lu kB\n"
- "VmLib: %lu kB\n",
- &P->vm_size, &P->vm_lock, &P->vm_rss, &P->vm_data,
- &P->vm_stack, &P->vm_exe, &P->vm_lib
- );
- else /* looks like an annoying kernel thread */
- {
- P->vm_size = 0;
- P->vm_lock = 0;
- P->vm_rss = 0;
- P->vm_data = 0;
- P->vm_stack = 0;
- P->vm_exe = 0;
- P->vm_lib = 0;
- }
+typedef struct status_table_struct {
+ unsigned char name[6]; // /proc/*/status field name
+ short len; // name length
+#ifdef LABEL_OFFSET
+ long offset; // jump address offset
+#else
+ void *addr;
+#endif
+} status_table_struct;
- // 2.1 SigPnd SigBlk SigIgn SigCat ("SigCat")
- // other SigPnd SigBlk SigIgn SigCgt
- // 2.5+ SigPnd ShdPnd SigBlk SigIgn SigCgt
+#ifdef LABEL_OFFSET
+#define F(x) {#x, sizeof(#x)-1, (int)(&&case_##x-&&base)},
+#else
+#define F(x) {#x, sizeof(#x)-1, &&case_##x},
+#endif
+#define NUL {"", 0, 0},
+
+// Derived from:
+// gperf -7 --language=ANSI-C --key-positions=1,3,4 -C -n -c sml.gperf
+
+static void status2proc(char *S, proc_t *restrict P){
+ static const unsigned char asso[] = {
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 15, 56, 56, 56, 56, 56,
+ 56, 56, 25, 30, 15, 3, 56, 5, 56, 3, 56, 56, 3, 56, 10, 56,
+ 18, 56, 13, 0, 30, 25, 0, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 30, 56, 8, 0, 0, 56, 25, 56, 5, 56, 56, 56, 0, 56, 56,
+ 56, 56, 56, 56, 0, 56, 56, 56, 0, 56, 56, 56, 56, 56, 56, 56
+ };
+ static const status_table_struct table[] = {
+ F(VmStk)
+ NUL
+ NUL
+ F(VmExe)
+ NUL
+ F(VmSize)
+ NUL
+ NUL
+ F(VmLib)
+ NUL
+ F(Name)
+ F(VmLck)
+ NUL
+ F(VmRSS)
+ NUL
+ NUL
+ NUL
+ NUL
+ F(ShdPnd)
+ NUL
+ F(Gid)
+ NUL
+ NUL
+ F(PPid)
+ NUL
+ NUL
+ NUL
+ NUL
+ F(SigIgn)
+ NUL
+ F(State)
+ NUL
+ NUL
+ F(Pid)
+ NUL
+ F(Tgid)
+ NUL
+ NUL
+ NUL
+ NUL
+ F(Uid)
+ NUL
+ NUL
+ F(SigPnd)
+ NUL
+ F(VmData)
+ NUL
+ NUL
+ NUL
+ NUL
+ F(SigBlk)
+ NUL
+ NUL
+ NUL
+ NUL
+ F(SigCgt)
+ NUL
+ NUL
+ NUL
+ NUL
+ NUL
+ NUL
+ NUL
+ NUL
+ };
+
+#undef F
+#undef NUL
+
+ENTER(0x220);
+
+ P->vm_size = 0;
+ P->vm_lock = 0;
+ P->vm_rss = 0;
+ P->vm_data = 0;
+ P->vm_stack= 0;
+ P->vm_exe = 0;
+ P->vm_lib = 0;
+
+ goto base;
- tmp = strstr (S,"SigPnd:");
- if(likely(tmp)) sscanf (tmp,
-#ifdef SIGNAL_STRING
- "SigPnd: %s SigBlk: %s SigIgn: %s %*s %s",
- P->signal, P->blocked, P->sigignore, P->sigcatch
+ for(;;){
+ char *colon;
+ status_table_struct entry;
+
+ // advance to next line
+ S = strchr(S, '\n');
+ if(unlikely(!S)) break; // if no newline
+ S++;
+
+ // examine a field name (hash and compare)
+ base:
+ if(unlikely(!*S)) break;
+ entry = table[63 & (asso[S[3]] + asso[S[2]] + asso[S[0]])];
+ colon = strchr(S, ':');
+ if(unlikely(!colon)) break;
+ if(unlikely(colon[1]!='\t')) break;
+ if(unlikely(colon-S != entry.len)) continue;
+ if(unlikely(memcmp(entry.name,S,colon-S))) continue;
+
+ S = colon+2; // past the '\t'
+
+#ifdef LABEL_OFFSET
+ goto *(&&base + entry.offset);
#else
- "SigPnd: %Lx SigBlk: %Lx SigIgn: %Lx %*s %Lx",
- &P->signal, &P->blocked, &P->sigignore, &P->sigcatch
+ goto *entry.addr;
#endif
- );
- else fprintf(stderr, "Internal error!\n");
-}
+ case_Gid:
+ P->rgid = strtol(S,&S,10);
+ P->egid = strtol(S,&S,10);
+ P->sgid = strtol(S,&S,10);
+ P->fgid = strtol(S,&S,10);
+ continue;
+ case_Name:{
+ int i = 0;
+ while(i < sizeof P->cmd - 1){
+ int c = *S++;
+ if(unlikely(c=='\n')) break;
+ if(unlikely(c=='\0')) return; // should never happen
+ if(unlikely(c=='\\')){
+ c = *S++;
+ if(c=='\n') break; // should never happen
+ if(!c) break; // should never happen
+ if(c=='n') c='\n'; // else we assume it is '\\'
+ }
+ P->cmd[i++] = c;
+ }
+ P->cmd[i] = '\0';
+ continue;
+ }
+ case_PPid:
+ P->ppid = strtol(S,&S,10);
+ continue;
+ case_Pid:
+ P->pid = strtol(S,&S,10);
+ continue;
+
+ case_ShdPnd:
+ memcpy(P->signal, S, 16);
+ P->signal[16] = '\0';
+ continue;
+ case_SigBlk:
+ memcpy(P->blocked, S, 16);
+ P->blocked[16] = '\0';
+ continue;
+ case_SigCgt:
+ memcpy(P->sigcatch, S, 16);
+ P->sigcatch[16] = '\0';
+ continue;
+ case_SigIgn:
+ memcpy(P->sigignore, S, 16);
+ P->sigignore[16] = '\0';
+ continue;
+ case_SigPnd:
+ memcpy(P->signal, S, 16);
+ P->signal[16] = '\0';
+ continue;
+
+ case_State:
+ P->state = *S;
+ continue;
+ case_Tgid:
+ P->tgid = strtol(S,&S,10);
+ continue;
+ case_Uid:
+ P->ruid = strtol(S,&S,10);
+ P->euid = strtol(S,&S,10);
+ P->suid = strtol(S,&S,10);
+ P->fuid = strtol(S,&S,10);
+ continue;
+ case_VmData:
+ P->vm_data = strtol(S,&S,10);
+ continue;
+ case_VmExe:
+ P->vm_exe = strtol(S,&S,10);
+ continue;
+ case_VmLck:
+ P->vm_lock = strtol(S,&S,10);
+ continue;
+ case_VmLib:
+ P->vm_lib = strtol(S,&S,10);
+ continue;
+ case_VmRSS:
+ P->vm_rss = strtol(S,&S,10);
+ continue;
+ case_VmSize:
+ P->vm_size = strtol(S,&S,10);
+ continue;
+ case_VmStk:
+ P->vm_stack = strtol(S,&S,10);
+ continue;
+ }
+LEAVE(0x220);
+}
+///////////////////////////////////////////////////////////////////////
// Reads /proc/*/stat files, being careful not to trip over processes with
// names like ":-) 1 2 3 4 5 6".
@@ -181,6 +324,8 @@ static void stat2proc(const char* S, proc_t *restrict P) {
unsigned num;
char* tmp;
+ENTER(0x160);
+
/* fill in default values for older kernels */
P->exit_signal = SIGCHLD;
P->processor = 0;
@@ -225,8 +370,11 @@ static void stat2proc(const char* S, proc_t *restrict P) {
/* -- Linux 2.2.8 to 2.5.17 end here -- */
&P->rtprio, &P->sched /* both added to 2.5.18 */
);
+LEAVE(0x160);
}
+/////////////////////////////////////////////////////////////////////////
+
static void statm2proc(const char* s, proc_t *restrict P) {
int num;
num = sscanf(s, "%ld %ld %ld %ld %ld %ld %ld",
@@ -243,9 +391,9 @@ static int file2str(const char *directory, const char *what, char *ret, int cap)
fd = open(filename, O_RDONLY, 0);
if(unlikely(fd==-1)) return -1;
num_read = read(fd, ret, cap - 1);
- if(unlikely(num_read<=0)) num_read = -1;
- else ret[num_read] = 0;
close(fd);
+ if(unlikely(num_read<=0)) return -1;
+ ret[num_read] = '\0';
return num_read;
}
@@ -329,8 +477,8 @@ int read_cmdline(char *restrict const dst, unsigned sz, unsigned pid){
dst[n] = '\0';
i=n;
while(i--){
- int c = dst[i];
- if(c<' ' || c>'~') dst[i]=' ';
+ int c = dst[i];
+ if(c<' ' || c>'~') dst[i]=' ';
}
}
return n;
diff --git a/proc/readproc.h b/proc/readproc.h
index 88fe775..2ac033b 100644
--- a/proc/readproc.h
+++ b/proc/readproc.h
@@ -133,6 +133,7 @@ typedef struct proc_t {
session, /* session id */
tty, /* full device number of controlling terminal */
tpgid, /* terminal process group id */
+ tgid, /* thread group ID */
exit_signal, /* might not be SIGCHLD */
processor; /* current (or most recent?) CPU */
#ifdef FLASK_LINUX