[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