[PATCH]count signals too with -c option
Shen Feng
shen at cn.fujitsu.com
Tue Aug 21 02:26:04 UTC 2007
Hi,
I fix the patch. I add an option g that should be used with the option c
at the same time.
>
> i.e. line up number of signals with number of calls and names with
> names. Also, I included a "fatal" column lined up with "errors".
> That would distinguish how many WIFSIGNALED exits strace saw, and
> that total could only be >1 when tracing multiple threads or
> processes.
>
But I'm not very sure my implementation about fatal is right.
I cannot understand why the total of fatal could only be >1
when tracing multiple threads or process.
The following is the changelog and the patch.
* defs.h (count_signal): Declare a new function.
* count.c (struct signal_counts): Define it.
(count_signal): New function.
(signal_cmp): New function.
(sig_count_cmp): New function.
(set_sortby): Add sort function for signal.
(call_summary_signal_pers): New function.
(call_summary): Add signal count report.
*strace.c (gflag): Add g option support.
(usage): Likewise.
(main): Likewise.
(trace): Add count signal support.
diff -upr strace-4.5.15/count.c strace-4.5.15.new/count.c
--- strace-4.5.15/count.c 2006-12-22 05:15:04.000000000 +0800
+++ strace-4.5.15.new/count.c 2007-08-21 09:04:12.000000000 +0800
@@ -45,6 +45,18 @@ struct call_counts {
static struct call_counts *countv[SUPPORTED_PERSONALITIES];
#define counts (countv[current_personality])
+extern int gflag;
+
+struct signal_counts {
+ int calls;
+ int fatal;
+};
+
+static struct signal_counts *sigcountv[SUPPORTED_PERSONALITIES];
+#define sigcounts (sigcountv[current_personality])
+
+static int nsignals_max;
+
static struct timeval shortest = { 1000000, 0 };
int
@@ -105,6 +117,51 @@ count_syscall(struct tcb *tcp, struct ti
return 0;
}
+int count_signal(int sig, int fatal)
+{
+ if (!sigcounts)
+ {
+ if (sig < nsignals)
+ nsignals_max = nsignals;
+ else
+ nsignals_max = sig+1;
+ sigcounts = calloc(nsignals_max, sizeof(*sigcounts));
+ if (!sigcounts)
+ {
+ fprintf(stderr,
+ "strace: out of memory for signal counts\n");
+ exit(1);
+ }
+ }
+ if (sig < nsignals_max)
+ {
+ if (fatal)
+ sigcounts[sig].fatal++;
+ else
+ sigcounts[sig].calls++;
+ }
+ else
+ {
+ /* reallocate signal counting table*/
+ sigcounts = realloc(sigcounts, (sig+1)*sizeof(*sigcounts));
+ if (!sigcounts)
+ {
+ fprintf(stderr,
+ "strace: out of memory for signal counts\n");
+ exit(1);
+ }
+ memset(sigcounts+nsignals_max*sizeof(*sigcounts), 0,
+ (sig-nsignals_max)*sizeof(*sigcounts));
+ nsignals_max = sig+1;
+ sigcounts[sig].calls++;
+ if (fatal)
+ sigcounts[sig].fatal++;
+ else
+ sigcounts[sig].calls++;
+ }
+ return 0;
+}
+
static int
time_cmp(void *a, void *b)
{
@@ -120,6 +177,13 @@ syscall_cmp(void *a, void *b)
}
static int
+signal_cmp(void *a, void *b)
+{
+ return strcmp(signame(*((int *) a)),
+ signame(*((int *) b)));
+}
+
+static int
count_cmp(void *a, void *b)
{
int m = counts[*((int *) a)].calls;
@@ -128,20 +192,43 @@ count_cmp(void *a, void *b)
return (m < n) ? 1 : (m > n) ? -1 : 0;
}
+static int
+sig_count_cmp(void *a, void *b)
+{
+ int m = sigcounts[*((int *) a)].calls;
+ int n = sigcounts[*((int *) b)].calls;
+
+ return (m < n) ? 1 : (m > n) ? -1 : 0;
+}
+
+
static int (*sortfun)();
+static int (*sig_sortfun)();
static struct timeval overhead = { -1, -1 };
void
set_sortby(char *sortby)
{
if (strcmp(sortby, "time") == 0)
+ {
sortfun = time_cmp;
+ sig_sortfun = NULL;
+ }
else if (strcmp(sortby, "calls") == 0)
+ {
sortfun = count_cmp;
+ sig_sortfun = sig_count_cmp;
+ }
else if (strcmp(sortby, "name") == 0)
+ {
sortfun = syscall_cmp;
+ sig_sortfun = signal_cmp;
+ }
else if (strcmp(sortby, "nothing") == 0)
+ {
sortfun = NULL;
+ sig_sortfun = NULL;
+ }
else
{
fprintf(stderr, "invalid sortby: `%s'\n", sortby);
@@ -226,6 +313,46 @@ call_summary_pers(FILE *outf)
call_cum, error_str, "total");
}
+static void
+call_summary_signal_pers(FILE *outf)
+{
+ int i, j;
+ char *dashes = "-------------------------";
+ int call_cum = 0, fatal_sum = 0;
+ int *sorted_count = calloc(sizeof(int), nsignals_max);
+
+ fprintf(outf, "%30.30s %9.9s %9.9s %s\n", " ", "signals",
+ "fatal", "signal name");
+ fprintf(outf, "%30.30s %9.9s %9.9s %-16.16s\n", " ",
+ dashes, dashes, dashes);
+ for (i = 0; i < nsignals_max; i++)
+ {
+ sorted_count[i] = i;
+ if (sigcounts == NULL || sigcounts[i].calls == 0)
+ continue;
+ call_cum += sigcounts[i].calls;
+ fatal_sum += sigcounts[i].fatal;
+ }
+ if (sigcounts && sig_sortfun)
+ qsort((void *) sorted_count, nsignals_max, sizeof(int), sig_sortfun);
+ if (sigcounts)
+ {
+ for(i=0; i<nsignals_max; i++)
+ {
+ j = sorted_count[i];
+ if (sigcounts[j].calls == 0)
+ continue;
+ fprintf(outf, "%30.30s %9d %9d %s\n", " ", sigcounts[j].calls,
+ sigcounts[j].fatal, signame(j));
+ }
+ }
+
+ free(sorted_count);
+ fprintf(outf, "%30.30s %9.9s %9.9s %-16.16s\n", " ",
+ dashes, dashes, dashes);
+ fprintf(outf, "%30.30s %9d %9d %s\n", " ", call_cum, fatal_sum, "total");
+}
+
void
call_summary(FILE *outf)
{
@@ -243,6 +370,8 @@ call_summary(FILE *outf)
"System call usage summary for %u bit mode:\n",
personality_wordsize[current_personality] * 8);
call_summary_pers(outf);
+ if (gflag)
+ call_summary_signal_pers(outf);
}
if (old_pers != current_personality)
diff -upr strace-4.5.15/defs.h strace-4.5.15.new/defs.h
--- strace-4.5.15/defs.h 2007-01-16 04:25:52.000000000 +0800
+++ strace-4.5.15.new/defs.h 2007-08-20 16:15:49.000000000 +0800
@@ -439,6 +439,7 @@ extern int get_scno P((struct tcb *));
extern long known_scno P((struct tcb *));
extern int trace_syscall P((struct tcb *));
extern int count_syscall P((struct tcb *, struct timeval *));
+extern int count_signal P((int, int));
extern void printxval P((const struct xlat *, int, const char *));
extern int printargs P((struct tcb *));
extern int addflags P((const struct xlat *, int));
diff -upr strace-4.5.15/strace.c strace-4.5.15.new/strace.c
--- strace-4.5.15/strace.c 2006-12-14 05:55:39.000000000 +0800
+++ strace-4.5.15.new/strace.c 2007-08-21 10:17:27.000000000 +0800
@@ -64,7 +64,7 @@
#endif
int debug = 0, followfork = 0, followvfork = 0;
-int dtime = 0, cflag = 0, xflag = 0, qflag = 0;
+int dtime = 0, cflag = 0, xflag = 0, qflag = 0, gflag =0;
static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
/* Sometimes we want to print only succeeding syscalls. */
@@ -142,6 +142,7 @@ usage: strace [-dffhiqrtttTvVxx] [-a col
-c -- count time, calls, and errors for each syscall and report summary\n\
-f -- follow forks, -ff -- with output into separate files\n\
-F -- attempt to follow vforks, -h -- print help message\n\
+-g -- count signals too when count syscalls\n\
-i -- print instruction pointer at time of syscall\n\
-q -- suppress messages about attaching, detaching, etc.\n\
-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs\n\
@@ -349,7 +350,7 @@ char *argv[];
qualify("verbose=all");
qualify("signal=all");
while ((c = getopt(argc, argv,
- "+cdfFhiqrtTvVxza:e:o:O:p:s:S:u:E:")) != EOF) {
+ "+cdfFghiqrtTvVxza:e:o:O:p:s:S:u:E:")) != EOF) {
switch (c) {
case 'c':
cflag++;
@@ -364,6 +365,9 @@ char *argv[];
case 'F':
followvfork++;
break;
+ case 'g':
+ gflag++;
+ break;
case 'h':
usage(stdout, 0);
break;
@@ -1980,6 +1984,9 @@ trace()
}
#endif
}
+ if (cflag && gflag && (qual_flags[what] & QUAL_SIGNAL)) {
+ count_signal(what, 0);
+ }
break;
case PR_FAULTED:
if (!cflag && (qual_flags[what] & QUAL_FAULT)) {
@@ -2240,6 +2247,10 @@ Process %d attached (waiting for parent)
"");
printtrailer(tcp);
}
+ if (cflag && gflag
+ && (qual_flags[WTERMSIG(status)] & QUAL_SIGNAL)) {
+ count_signal(WTERMSIG(status), WIFSIGNALED(status));
+ }
#ifdef TCB_GROUP_EXITING
handle_group_exit(tcp, -1);
#else
@@ -2366,6 +2377,10 @@ Process %d attached (waiting for parent)
strsignal(WSTOPSIG(status)), pc, addr);
printtrailer(tcp);
}
+ if (cflag && gflag
+ && (qual_flags[WSTOPSIG(status)] & QUAL_SIGNAL)) {
+ count_signal(WSTOPSIG(status), 0);
+ }
if (((tcp->flags & TCB_ATTACHED) ||
tcp->nclone_threads > 0) &&
!sigishandled(tcp, WSTOPSIG(status))) {
Best Regards,
More information about the Strace-devel
mailing list