+2009-01-06 Denys Vlasenko <dvlasenk@redhat.com>
+
+ Output format fixes, improving the situation after recent
+ change which added beeter handling of processes suddenly
+ disappearing. Now we often do not finish last line
+ before exiting in those cases.
+ The only change affecting something other than output
+ is change in umovestr where we were calling
+ abort() on ptrace error.
+
+ * strace.c (trace): If trace_syscall() failed with ESRCH,
+ finish current output line with " <unfinished ...>".
+ (mp_ioctl): While we are at it, fix gross style mismatch
+ in this function definition. No code chages.
+ * syscall.c (trace_syscall): If decode fails on syscall exit,
+ finish current output line with "= ? <unavailable>".
+ * util.c (umoven): Do not complain if error is ESRCH.
+ (umovestr): Do not complain and do not abort() if error is ESRCH.
+ * defs.h: Remove unused tcp parameter from printtrailer().
+ * process.c: Adjust printtrailer() calls accordingly.
+ * strace.c: Adjust printtrailer() calls accordingly.
+ * syscall.c: Adjust printtrailer() calls accordingly.
+
2009-01-06 Denys Vlasenko <dvlasenk@redhat.com>
* desc.c (printflock): Fix display of fcntl(F_SETLK) on
extern void print_sigset P((struct tcb *, long, int));
extern void printsignal P((int));
extern void printleader P((struct tcb *));
-extern void printtrailer P((struct tcb *));
+extern void printtrailer P((void));
extern void tabto P((int));
extern void call_summary P((FILE *));
extern void tprint_iov P((struct tcb *, unsigned long, unsigned long));
tprintf("%ld) ", tcp->u_arg[0]);
tabto(acolumn);
tprintf("= ?");
- printtrailer(tcp);
+ printtrailer();
return 0;
}
}
else
catch_sigstop = 1;
- if (catch_sigstop)
+ if (catch_sigstop) {
for (;;) {
#ifdef __WALL
if (wait4(tcp->pid, &status, __WALL, NULL) < 0) {
if (error < 0)
break;
}
+ }
#endif /* LINUX */
#if defined(SUNOS4)
"cleanup: looking at pid %u\n", tcp->pid);
if (tcp_last &&
(!outfname || followfork < 2 || tcp_last == tcp)) {
- tprintf(" <unfinished ...>\n");
- tcp_last = NULL;
+ tprintf(" <unfinished ...>");
+ printtrailer();
}
if (tcp->flags & TCB_ATTACHED)
detach(tcp, 0);
printleader(tcp);
tprintf("--- %s (%s) ---",
signame(what), strsignal(what));
- printtrailer(tcp);
+ printtrailer();
#ifdef PR_INFO
if (tcp->status.PR_INFO.si_signo == what) {
printleader(tcp);
tprintf(" siginfo=");
printsiginfo(&tcp->status.PR_INFO, 1);
- printtrailer(tcp);
+ printtrailer();
}
#endif
}
if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
printleader(tcp);
tprintf("=== FAULT %d ===", what);
- printtrailer(tcp);
+ printtrailer();
}
break;
#ifdef FREEBSD
WCOREDUMP(status) ? "(core dumped) " :
#endif
"");
- printtrailer(tcp);
+ printtrailer();
}
#ifdef TCB_GROUP_EXITING
handle_group_exit(tcp, -1);
tprintf("--- %s (%s) @ %lx (%lx) ---",
signame(WSTOPSIG(status)),
strsignal(WSTOPSIG(status)), pc, addr);
- printtrailer(tcp);
+ printtrailer();
}
if (((tcp->flags & TCB_ATTACHED) ||
tcp->nclone_threads > 0) &&
if (interrupted)
return 0;
if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
- if (tcp->flags & TCB_ATTACHED)
+ /* ptrace() failed in trace_syscall() with ESRCH.
+ * Likely a result of process disappearing mid-flight.
+ * Observed case: exit_group() terminating
+ * all processes in thread group. In this case, threads
+ * "disappear" in an unpredictable moment without any
+ * notification to strace via wait().
+ */
+ if (tcp->flags & TCB_ATTACHED) {
+ if (tcp_last) {
+ /* Do we have dangling line "syscall(param, param"?
+ * Finish the line then. We cannot
+ */
+ tcp_last->flags |= TCB_REPRINT;
+ tprintf(" <unfinished ...>");
+ printtrailer();
+ }
detach(tcp, 0);
- else {
+ } else {
ptrace(PTRACE_KILL,
tcp->pid, (char *) 1, SIGTERM);
droptcb(tcp);
}
void
-printtrailer(tcp)
-struct tcb *tcp;
+printtrailer(void)
{
tprintf("\n");
tcp_last = NULL;
#ifdef HAVE_MP_PROCFS
-int mp_ioctl (int fd, int cmd, void *arg, int size) {
-
+int
+mp_ioctl(int fd, int cmd, void *arg, int size)
+{
struct iovec iov[2];
int n = 1;
iov[1].iov_len = size;
}
- return writev (fd, iov, n);
+ return writev(fd, iov, n);
}
#endif
if (dtime)
gettimeofday(&tv, NULL);
+ /* BTW, why we don't just memorize syscall no. on entry
+ * in tcp->something?
+ */
scno_good = res = get_scno(tcp);
if (res == 0)
return res;
if (res != 1) {
tprintf(") ");
tabto(acolumn);
+ tprintf("= ? <unavailable>");
+ printtrailer();
tcp->flags &= ~TCB_INSYSCALL;
return res;
}
tprintf(" <%ld.%06ld>",
(long) tv.tv_sec, (long) tv.tv_usec);
}
- printtrailer(tcp);
+ printtrailer();
dumpio(tcp);
if (fflush(tcp->outf) == EOF)
* at address `addr' to our space at `laddr'
*/
int
-umoven(tcp, addr, len, laddr)
-struct tcb *tcp;
-long addr;
-int len;
-char *laddr;
+umoven(struct tcb *tcp, long addr, int len, char *laddr)
{
-
#ifdef LINUX
int pid = tcp->pid;
int n, m;
return 0;
}
/* But if not started, we had a bogus address. */
- if (addr != 0 && errno != EIO)
+ if (addr != 0 && errno != EIO && errno != ESRCH)
perror("ptrace: umoven");
return -1;
}
/* Ran into 'end of memory' - stupid "printpath" */
return 0;
}
- if (addr != 0 && errno != EIO)
+ if (addr != 0 && errno != EIO && errno != ESRCH)
perror("ptrace: umoven");
return -1;
}
errno = 0;
u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
if (errno) {
- perror("umoven");
+ if (errno != ESRCH)
+ perror("umoven");
return -1;
}
memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len));
errno = 0;
u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0);
if (errno) {
- perror("umoven");
+ if (errno != ESRCH)
+ perror("umoven");
return -1;
}
memcpy(laddr, u.x, m = MIN(sizeof(long), len));
n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr);
if (ptrace(PTRACE_READDATA, pid,
(char *) addr, len, laddr) < 0) {
- perror("umoven: ptrace(PTRACE_READDATA, ...)");
- abort();
+ if (errno != ESRCH) {
+ perror("umoven: ptrace(PTRACE_READDATA, ...)");
+ abort();
+ }
return -1;
}
len -= n;
* for a terminating zero byte.
*/
int
-umovestr(tcp, addr, len, laddr)
-struct tcb *tcp;
-long addr;
-int len;
-char *laddr;
+umovestr(struct tcb *tcp, long addr, int len, char *laddr)
{
#ifdef USE_PROCFS
#ifdef HAVE_MP_PROCFS
/* Ran into 'end of memory' - stupid "printpath" */
return 0;
}
- if (addr != 0 && errno != EIO)
+ if (addr != 0 && errno != EIO && errno != ESRCH)
perror("umovestr");
return -1;
}
/* Ran into 'end of memory' - stupid "printpath" */
return 0;
}
- if (addr != 0 && errno != EIO)
+ if (addr != 0 && errno != EIO && errno != ESRCH)
perror("umovestr");
return -1;
}