File: signaltester.c

package info (click to toggle)
scratchbox2 2.2.4-1debian1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd, wheezy
  • size: 5,392 kB
  • ctags: 5,239
  • sloc: ansic: 21,734; sh: 4,360; perl: 2,170; cpp: 1,913; makefile: 610; python: 184
file content (168 lines) | stat: -rw-r--r-- 4,270 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/* signaltester, catch & print signals
 * This is used for testing out sb2-monitor.
 *
 * Copyright (c) 2008 Nokia Corporation. All rights reserved.
 * Author: Lauri T. Aarnio
 * Licensed under LGPL version 2.1, see top level LICENSE file for details.
*/

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#define _GNU_SOURCE /* to get strsignal(), a non-standard extension */
#include <string.h>

static int signals_received = 0;

static void signal_handler(int sig, siginfo_t *info, void *ptr)
{
	(void)ptr; /* unused param */

	signals_received++;
	
	fprintf(stderr, "\nGot signal %d (%s), received %d signals\n",
		sig, strsignal(sig), signals_received);

	switch (sig) {
	case SIGILL: case SIGFPE: case SIGSEGV:
		if ((info->si_code != SI_USER) &&
		   (info->si_code != SI_QUEUE)) {
			/* the signal is a real, fatal, deadly 
			 * that must not be ignored. */
			fprintf(stderr, "Deadly signal\n");
			exit(249);
		}
		/* else it is user-generated signal */
		break;

	case SIGTSTP:
		/* Job control.. stop request from tty */
		fprintf(stderr, "Stopping myself.\n");
		raise(SIGSTOP);
		return;
	}

	if (info->si_code == SI_QUEUE) {
		fprintf(stderr, "SI_QUEUE int=%d ptr=0x%x\n",
			info->si_value.sival_int,
			(int)(info->si_value.sival_ptr));
	} else if (info->si_code == SI_USER) {
		fprintf(stderr, "SI_USER\n");
	} else {
		fprintf(stderr, "si_code is %d\n", info->si_code);
	}
}

static void initialize_signal_handler(int sig)
{
	struct	sigaction	act;

	memset(&act, 0, sizeof(act));

	act.sa_sigaction = signal_handler;
	act.sa_flags = SA_SIGINFO;

	/* block all other signals while this signal is being processed */
	sigfillset(&act.sa_mask);

	sigaction(sig, &act, NULL);
}

/* Set up a signal handler for all signals that can be caught. */
static void catch_all_signals(void)
{
	/* order here tries to follows the numerical order of signals 
	 * on Linux (see signal(7)) and Mac OS X (see signal(2))
	*/
	initialize_signal_handler(SIGHUP); /* 1 */
	initialize_signal_handler(SIGINT);
	initialize_signal_handler(SIGQUIT);
	initialize_signal_handler(SIGILL);
	initialize_signal_handler(SIGTRAP); /* 5 */
	initialize_signal_handler(SIGABRT);
#ifdef SIGIOT /* old name for SIGABRT */
	initialize_signal_handler(SIGIOT);
#endif
#ifdef SIGEMT
	initialize_signal_handler(SIGEMT);
#endif
	initialize_signal_handler(SIGFPE);

	/* SIGKILL, 9, cannot be caught or ignored */

	initialize_signal_handler(SIGBUS);
	initialize_signal_handler(SIGSEGV); /* 11 */
	initialize_signal_handler(SIGSYS);
	initialize_signal_handler(SIGPIPE);
	initialize_signal_handler(SIGALRM);
	initialize_signal_handler(SIGTERM); /* 15 */
	initialize_signal_handler(SIGURG);

	/* SIGSTOP, 17, cannot be caught or ignored */

	initialize_signal_handler(SIGTSTP);
	initialize_signal_handler(SIGCONT);
	initialize_signal_handler(SIGCHLD); /* 20 */
	initialize_signal_handler(SIGTTIN);

	initialize_signal_handler(SIGTTOU);
	initialize_signal_handler(SIGIO);
	initialize_signal_handler(SIGXCPU);
	initialize_signal_handler(SIGXFSZ); /* 25 */
	initialize_signal_handler(SIGVTALRM);
	initialize_signal_handler(SIGPROF);
	initialize_signal_handler(SIGWINCH);
#ifdef SIGPWR
	initialize_signal_handler(SIGPWR);
#endif
#ifdef SIGLOST
	initialize_signal_handler(SIGLOST);
#endif
#ifdef SIGINFO
	initialize_signal_handler(SIGINFO);
#endif
	initialize_signal_handler(SIGUSR1);
	initialize_signal_handler(SIGUSR2);
#ifdef SIGTHR
	initialize_signal_handler(SIGTHR);
#endif
}

int main(int argc, char *argv[])
{
	char	*progname = argv[0];
	int	num_signals_to_receive = 10;
	int	opt;
	
	while ((opt = getopt(argc, argv, "n:g")) != -1) {
		switch (opt) {
		case 'n': num_signals_to_receive = atoi(optarg); break;
		case 'g': setpgrp(); break;
		}
	}

	/* check parameters */
	if (optind < argc) {
		fprintf(stderr, "Wrong number of parameters");
		exit(1);
	}

	fprintf(stderr, "\n%s: PID=%d PGID=%d: waiting for %d signals\n", 
		progname, (int)getpid(), (int)getpgrp(),
		num_signals_to_receive);

	catch_all_signals();

	/* all initializations done, wait until the child has finished. */
	while (signals_received < num_signals_to_receive) {
		if (sleep(5)) fprintf(stderr, "S");
		else fprintf(stderr, ".");
	}

	return(0);
}