1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <signal.h>
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h>
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdlib.h>
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <sys/types.h>
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <unistd.h>
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* What does this test do?  It checks that valgrind's signal frame
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   building mechanism can create at least 4MB of signal delivery
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frames, hence that it can actually expand the stack by that much
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   when delivering signals.  A fair-enough thing to want to test.
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   It does this by getting into the signal handler, and then
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   recursively invoking the handler by sending itself the signal
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   again, until the stack has grown to 4MB from the starting frame
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (main).
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Consequence is: it is essential that we do not disable delivery of
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   further signals within the handler itself, else the kernel will
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   wait till the handler exits before delivering the next signal, the
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   frame will be cleared, the stack will never grow, and we'll be in
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   an infinite loop.
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Hence we *must* give the SA_NODEFER flag when setting up the
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   handler.
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic char *deep;
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define SIZE	(4*1024*1024)
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void handler(int sig)
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	char here;
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (&here < deep) {
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		printf("PASSED\n");
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		exit(0);
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	kill(getpid(), SIGUSR1);
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main()
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	struct sigaction sa;
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	char here;
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	deep = &here - SIZE;
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	sa.sa_handler = handler;
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	sa.sa_flags = SA_NODEFER;
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	sigemptyset(&sa.sa_mask);
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	sigaction(SIGUSR1, &sa, NULL);
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	kill(getpid(), SIGUSR1);
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	printf("FAILED\n");
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	exit(1);
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
62