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