[PATCH]count signals too with -c option
Shen Feng
shen at cn.fujitsu.com
Thu Sep 20 08:10:52 UTC 2007
Hello,
Is this patch OK?
Shen Feng Wrote:
> 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,
>
>
--
Best Regards,
--------------------------------------------------
Shen Feng
Development Dept.I
Nanjing Fujitsu Nanda Software Tech. Co., Ltd.(FNST)
8/F., Civil Defense Building, No.189 Guangzhou Road,
Nanjing, 210029, China
PHONE:+86-25-86630566-950
COINS:79955-950
FAX:+86-25-83317685
MAIL:shen at cn.fujitsu.com
--------------------------------------------------
More information about the Strace-devel
mailing list