From a44f9696e45f5bb51c6ec37c0ef95dc2cdfd4c8a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko <vda.linux@googlemail.com> Date: Wed, 21 Mar 2012 11:06:20 +0100 Subject: [PATCH] Replace reprinting decision logic After this change, we no longer need to decide when we need to set TCB_REPRINT, and when we don't: it's never needed :) Well, almost. That pesky pid-changing execve needs special treatment. If not it, it'd be possible to nuke TCB_REPRINT... While at it, fix a case of mishandled -C. * strace.c (printleader): Do not set TCB_REPRINT. (trace): Set TCB_REPRINT only for execve with changing pid. Fix mishandling of -C. * syscall.c (trace_syscall_entering): Do not clear TCB_REPRINT. (trace_syscall_exiting): Replace reprinting decision logic. Remove call to printargs(): it is known to just return 0 here. Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> --- strace.c | 7 ++++--- syscall.c | 47 ++++++++++++++++++++++------------------------- 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/strace.c b/strace.c index ad29bb40..789ea925 100644 --- a/strace.c +++ b/strace.c @@ -560,7 +560,6 @@ printleader(struct tcb *tcp) * didn't finish ("SIGKILL nuked us after syscall entry" etc). */ tprints(" <unfinished ...>\n"); - printing_tcp->flags |= TCB_REPRINT; printing_tcp->curcol = 0; } } @@ -1943,11 +1942,11 @@ trace(void) tcp = execve_thread; if (tcp) { tcp->pid = pid; - tcp->flags |= TCB_REPRINT; - if (!cflag) { + if (cflag != CFLAG_ONLY_STATS) { printleader(tcp); tprintf("+++ superseded by execve in pid %lu +++\n", old_pid); line_ended(); + tcp->flags |= TCB_REPRINT; } } } @@ -2103,6 +2102,8 @@ trace(void) /* Nonzero (true) if tracee is stopped by signal * (as opposed to "tracee received signal"). + * TODO: shouldn't we check for errno == EINVAL too? + * We can get ESRCH instead, you know... */ stopped = (ptrace(PTRACE_GETSIGINFO, pid, 0, (long) &si) < 0); #ifdef USE_SEIZE diff --git a/syscall.c b/syscall.c index ac0f7699..663d678b 100644 --- a/syscall.c +++ b/syscall.c @@ -1469,7 +1469,6 @@ trace_syscall_entering(struct tcb *tcp) if (res != 1) { printleader(tcp); - tcp->flags &= ~TCB_REPRINT; if (scno_good != 1) tprints("????" /* anti-trigraph gap */ "("); else if (!SCNO_IN_RANGE(tcp->scno)) @@ -1518,7 +1517,6 @@ trace_syscall_entering(struct tcb *tcp) } printleader(tcp); - tcp->flags &= ~TCB_REPRINT; if (!SCNO_IN_RANGE(tcp->scno)) tprintf("syscall_%lu(", tcp->scno); else @@ -1918,25 +1916,6 @@ trace_syscall_exiting(struct tcb *tcp) } } - /* TODO: TCB_REPRINT is probably not necessary: - * we can determine whether reprinting is needed - * by examining printing_tcp. Something like: - * if not in -ff mode, and printing_tcp != tcp, - * then the log is not currently ends with *our* - * syscall entry output, but with something else, - * and we need to reprint. - * If we'd implement this, printing_tcp = tcp - * assignments in code below can be made more logical. - */ - - if (tcp->flags & TCB_REPRINT) { - printleader(tcp); - if (!SCNO_IN_RANGE(tcp->scno)) - tprintf("<... syscall_%lu resumed> ", tcp->scno); - else - tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name); - } - if (cflag) { struct timeval t = tv; count_syscall(tcp, &t); @@ -1945,8 +1924,27 @@ trace_syscall_exiting(struct tcb *tcp) } } + /* If not in -ff mode, and printing_tcp != tcp, + * then the log currently does not end with output + * of _our syscall entry_, but with something else. + * We need to say which syscall's return is this. + * + * Forced reprinting via TCB_REPRINT is used only by + * "strace -ff -oLOG test/threaded_execve" corner case. + * It's the only case when -ff mode needs reprinting. + */ + if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) { + tcp->flags &= ~TCB_REPRINT; + printleader(tcp); + if (!SCNO_IN_RANGE(tcp->scno)) + tprintf("<... syscall_%lu resumed> ", tcp->scno); + else + tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name); + } + printing_tcp = tcp; + if (res != 1) { - printing_tcp = tcp; + /* There was error in one of prior ptrace ops */ tprints(") "); tabto(); tprints("= ? <unavailable>\n"); @@ -1955,10 +1953,10 @@ trace_syscall_exiting(struct tcb *tcp) return res; } + sys_res = 0; if (!SCNO_IN_RANGE(tcp->scno) || (qual_flags[tcp->scno] & QUAL_RAW)) { - printing_tcp = tcp; - sys_res = printargs(tcp); + /* sys_res = printargs(tcp); - but it's nop on sysexit */ } else { /* FIXME: not_failing_only (IOW, option -z) is broken: * failure of syscall is known only after syscall return. @@ -1970,7 +1968,6 @@ trace_syscall_exiting(struct tcb *tcp) */ if (not_failing_only && tcp->u_error) goto ret; /* ignore failed syscalls */ - printing_tcp = tcp; sys_res = (*sysent[tcp->scno].sys_func)(tcp); } -- 2.40.0