]> granicus.if.org Git - strace/commitdiff
Implement -C option to combine regular and -c output
authorDmitry V. Levin <ldv@altlinux.org>
Sun, 28 Mar 2010 19:24:54 +0000 (19:24 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Wed, 7 Apr 2010 10:19:26 +0000 (10:19 +0000)
* 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
defs.h
strace.1
strace.c
syscall.c

diff --git a/count.c b/count.c
index 4e272a367a04c7cdceb2cdbe2028625a25266ef8..d0ea016947814fc763b39ccc2a6e5a0d364c3cf8 100644 (file)
--- 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 4797e96b735857f799be4cb673a134d76d9aee92..62b371917b8061c359c10290bcee5650fce3408a 100644 (file)
--- 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;
index d35a74e8a0576043fce2ae411f24eeee6248816a..aff8f412e1a376e009fedadada78e38286aebee5 100644 (file)
--- 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
index 2fb75c94144c18cd9251ca0354b5c89af80b9b11..40f89072517d75264d6b776e0401b671c020d14b 100644 (file)
--- 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;
index a56d7df44874389fbd1d171a94698d07a1e5555a..6a6fad80a7ee4f58cf0a3a8eff89f6ba59ed7a65 100644 (file)
--- 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;
 }