tag 355660 patch thanks
A partial patch is attached; I also fix an uninitialized integer that would result in the display of a uninitialized string in the (hypothetical?) case that a process is attached, but its commandline can't be read.
--- pstack.c 2006-03-06 19:20:28.000000000 -0500 +++ /tmp/pstack.c 2006-03-07 00:10:32.000000000 -0500 @@ -49,6 +49,7 @@ #include <stdlib.h> #include <stdio.h> #include <errno.h> +#include <limits.h> static int thePid; /* pid requested by caller. */ static struct { @@ -64,25 +65,20 @@ { int status; - errno = 0; - ptrace(PTRACE_ATTACH, pid, 0, 0); - - if (errno) + if (-1==ptrace(PTRACE_ATTACH, pid, 0, 0)) return errno; - waitpid (pid, &status, WUNTRACED); - /* If we failed due to an ECHILD, then retry with the __WCLONE flag. Note we loop as the the PID we get back may not be one we care about. */ - if (errno == ECHILD) { + if (-1==waitpid(pid, &status, WUNTRACED) && errno == ECHILD) { int x; errno = 0; while (1) { x = waitpid (-1, &status, (__WCLONE)); - if (x == pid || x < 0 || errno != 0) break; + if (x == pid || x < 0) break; } } @@ -100,9 +96,9 @@ if (threads.found) { for (i = 0; i < threads.npids; i++) { if (threads.pids[i] != thePid && threads.attached[i]) { - errno = 0; - ptrace(PTRACE_DETACH, threads.pids[i], 0, 0); - if (errno) perror("detach"); + if (-1==ptrace(PTRACE_DETACH, threads.pids[i], 0, 0)) { + perror("detach"); + } } } } @@ -110,9 +106,9 @@ /* Now attach from the thread we initially attached to. Note that the PTRACE_DETACH will continue the thread, so there is no need is issue a separate PTRACE_CONTINUE call. */ - ptrace(PTRACE_DETACH, thePid, 0, 0); - - return errno; + if (-1==ptrace(PTRACE_DETACH, thePid, 0, 0)) + return errno; + return 0; } static void handle_signal (int signum) @@ -244,7 +240,7 @@ if (!(sym = findLocalSym(name, syms))) return 0; errno = 0; *val = ptrace(PTRACE_PEEKDATA, pid, sym->st_value, 0); - if (errno) { + if (-1==*val && errno) { perror("ptrace"); quit("Could not read thread debug info."); } @@ -286,7 +282,7 @@ *pptr++ = pid; else if (descr && !errno) { tpid = ptrace(PTRACE_PEEKDATA, pid, descr + pidOff, 0); - if (!errno) + if (-1!=tpid || !errno) *pptr++ = tpid; } } @@ -414,7 +410,7 @@ for (errno = done = 0, addr = dyn->st_value; !done && !errno; addr += 8) { val = ptrace(PTRACE_PEEKDATA, pid, addr, 0); - if (errno) break; + if (-1==val && errno) break; switch (val) { case DT_NULL: done = 1; break; case DT_DEBUG: @@ -475,7 +471,7 @@ lm->l_addr = (Elf32_Addr) ptrace(PTRACE_PEEKDATA, pid, base + OFFSET(l_addr, *lm), 0); /* next element of link map chain */ - if (!errno) + if (-1!=(long)lm->l_addr || !errno) lm->l_next = (struct link_map *) ptrace(PTRACE_PEEKDATA, pid, base + OFFSET(l_next, *lm), 0); if (errno) { @@ -549,7 +545,7 @@ print_pc(pc); for ( ; !errno && fp; ) { nextfp = ptrace(PTRACE_PEEKDATA, pid, fp, 0); - if (errno) break; + if ((unsigned)-1==nextfp && errno) break; nargs = (nextfp - fp - 8) / 4; if (nargs > MAXARGS) nargs = MAXARGS; @@ -557,7 +553,7 @@ fputs(" (", stdout); for (i = 1; i <= nargs; i++) { arg = ptrace(PTRACE_PEEKDATA, pid, fp + 4 * (i + 1), 0); - if (errno) break; + if ((unsigned)-1==arg && errno) break; printf("%lx", arg); if (i < nargs) fputs(", ", stdout); } @@ -570,7 +566,7 @@ if (errno || !nextfp) break; pc = ptrace(PTRACE_PEEKDATA, pid, fp + 4, 0); fp = nextfp; - if (errno) break; + if ((unsigned)-1==pc && errno) break; print_pc(pc); } } @@ -585,9 +581,8 @@ static char *cmdLine(int pid) { - int fd, len, i; + int fd, len=-1, i; - fd = -1; sprintf(cmd, "/proc/%d/cmdline", pid); if ((fd = open(cmd, O_RDONLY)) >= 0 && (len = read(fd, cmd, sizeof(cmd))) > 0) { @@ -626,7 +621,8 @@ for (argc--, argv++; argc > 0; argc--, argv++) { char *endptr = NULL; thePid = strtol(*argv, &endptr, 0); - if (!*argv || *endptr || errno==ERANGE) + if (!*argv || *endptr || (errno==ERANGE && + (thePid==LONG_MIN || thePid==LONG_MAX))) usage(argv0, *argv); if (!thePid || thePid == getpid()) { fprintf(stderr, "Invalid PID %d\n", thePid);