From e3a7ef5a2a3ac31bfa0d3f9ce65981e51700073e Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Sun, 28 Mar 2010 19:24:54 +0000 Subject: [PATCH] Implement -C option to combine regular and -c output * defs.h (cflag_t): New enum. * strace.1: Document -C option. * strace.c (cflag): Update type. (main): Handle -C option. (trace): Update use of cflag. * count.c (count_syscall): Move clearing of TCB_INSYSCALL to ... * syscall.c (trace_syscall): ... here. Update use of cflag. Based on patch by Adrien Kunysz. --- count.c | 1 - defs.h | 9 ++++++++- strace.1 | 7 ++++++- strace.c | 33 ++++++++++++++++++++++++--------- syscall.c | 19 +++++++++++++------ 5 files changed, 51 insertions(+), 18 deletions(-) diff --git a/count.c b/count.c index 4e272a36..d0ea0169 100644 --- a/count.c +++ b/count.c @@ -50,7 +50,6 @@ static struct timeval shortest = { 1000000, 0 }; int count_syscall(struct tcb *tcp, struct timeval *tv) { - tcp->flags &= ~TCB_INSYSCALL; if (tcp->scno < 0 || tcp->scno >= nsyscalls) return 0; diff --git a/defs.h b/defs.h index 4797e96b..62b37191 100644 --- a/defs.h +++ b/defs.h @@ -456,10 +456,17 @@ extern const struct xlat open_access_modes[]; #define TRACE_SIGNAL 020 /* Trace signal-related syscalls. */ #define TRACE_DESC 040 /* Trace file descriptor-related syscalls. */ +typedef enum { + CFLAG_NONE = 0, + CFLAG_ONLY_STATS, + CFLAG_BOTH +} cflag_t; + extern struct tcb **tcbtab; extern int *qual_flags; extern int debug, followfork; -extern int dtime, cflag, xflag, qflag; +extern int dtime, xflag, qflag; +extern cflag_t cflag; extern int acolumn; extern unsigned int nprocs, tcbtabsize; extern int max_strlen; diff --git a/strace.1 b/strace.1 index d35a74e8..aff8f412 100644 --- a/strace.1 +++ b/strace.1 @@ -43,7 +43,7 @@ strace \- trace system calls and signals .SH SYNOPSIS .B strace [ -.B \-dffhiqrtttTvxx +.B \-CdffhiqrtttTvxx ] [ .BI \-a column @@ -243,6 +243,11 @@ program exit. On Linux, this attempts to show system time (CPU time spent running in the kernel) independent of wall clock time. If -c is used with -f or -F (below), only aggregate totals for all traced processes are kept. .TP +.B \-C +Like +.B \-c +but also print regular output while processes are running. +.TP .B \-d Show some debugging output of .B strace diff --git a/strace.c b/strace.c index 2fb75c94..40f89072 100644 --- a/strace.c +++ b/strace.c @@ -83,7 +83,8 @@ extern char *optarg; int debug = 0, followfork = 0; -int dtime = 0, cflag = 0, xflag = 0, qflag = 0; +int dtime = 0, xflag = 0, qflag = 0; +cflag_t cflag = CFLAG_NONE; static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0; /* * daemonized_tracer supports -D option. @@ -719,15 +720,27 @@ main(int argc, char *argv[]) qualify("verbose=all"); qualify("signal=all"); while ((c = getopt(argc, argv, - "+cdfFhiqrtTvVxz" + "+cCdfFhiqrtTvVxz" #ifndef USE_PROCFS "D" #endif "a:e:o:O:p:s:S:u:E:")) != EOF) { switch (c) { case 'c': - cflag++; - dtime++; + if (cflag == CFLAG_BOTH) { + fprintf(stderr, "%s: -c and -C are mutually exclusive options\n", + progname); + exit(1); + } + cflag = CFLAG_ONLY_STATS; + break; + case 'C': + if (cflag == CFLAG_ONLY_STATS) { + fprintf(stderr, "%s: -c and -C are mutually exclusive options\n", + progname); + exit(1); + } + cflag = CFLAG_BOTH; break; case 'd': debug++; @@ -838,7 +851,7 @@ main(int argc, char *argv[]) if (followfork > 1 && cflag) { fprintf(stderr, - "%s: -c and -ff are mutually exclusive options\n", + "%s: (-c or -C) and -ff are mutually exclusive options\n", progname); exit(1); } @@ -2144,7 +2157,8 @@ trace() } break; case PR_SIGNALLED: - if (!cflag && (qual_flags[what] & QUAL_SIGNAL)) { + if (cflag != CFLAG_ONLY_STATS + && (qual_flags[what] & QUAL_SIGNAL)) { printleader(tcp); tprintf("--- %s (%s) ---", signame(what), strsignal(what)); @@ -2160,7 +2174,8 @@ trace() } break; case PR_FAULTED: - if (!cflag && (qual_flags[what] & QUAL_FAULT)) { + if (cflag != CFLAGS_ONLY_STATS + && (qual_flags[what] & QUAL_FAULT)) { printleader(tcp); tprintf("=== FAULT %d ===", what); printtrailer(); @@ -2383,7 +2398,7 @@ Process %d attached (waiting for parent)\n", if (WIFSIGNALED(status)) { if (pid == strace_child) exit_code = 0x100 | WTERMSIG(status); - if (!cflag + if (cflag != CFLAG_ONLY_STATS && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) { printleader(tcp); tprintf("+++ killed by %s %s+++", @@ -2482,7 +2497,7 @@ Process %d attached (waiting for parent)\n", } continue; } - if (!cflag + if (cflag != CFLAG_ONLY_STATS && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) { unsigned long addr = 0; long pc = 0; diff --git a/syscall.c b/syscall.c index a56d7df4..6a6fad80 100644 --- a/syscall.c +++ b/syscall.c @@ -2369,7 +2369,7 @@ trace_syscall(struct tcb *tcp) long u_error; /* Measure the exit time as early as possible to avoid errors. */ - if (dtime) + if (dtime || cflag) gettimeofday(&tv, NULL); /* BTW, why we don't just memorize syscall no. on entry @@ -2407,8 +2407,15 @@ trace_syscall(struct tcb *tcp) tprintf(" resumed> "); } - if (cflag) - return count_syscall(tcp, &tv); + if (cflag) { + struct timeval t = tv; + int rc = count_syscall(tcp, &t); + if (cflag == CFLAG_ONLY_STATS) + { + tcp->flags &= ~TCB_INSYSCALL; + return rc; + } + } if (res != 1) { tprintf(") "); @@ -2647,9 +2654,9 @@ trace_syscall(struct tcb *tcp) return 0; } - if (cflag) { - gettimeofday(&tcp->etime, NULL); + if (cflag == CFLAG_ONLY_STATS) { tcp->flags |= TCB_INSYSCALL; + gettimeofday(&tcp->etime, NULL); return 0; } @@ -2669,7 +2676,7 @@ trace_syscall(struct tcb *tcp) return -1; tcp->flags |= TCB_INSYSCALL; /* Measure the entrance time as late as possible to avoid errors. */ - if (dtime) + if (dtime || cflag) gettimeofday(&tcp->etime, NULL); return sys_res; }