[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