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

/* What does this test do?  It checks that valgrind's signal frame
   building mechanism can create at least 4MB of signal delivery
   frames, hence that it can actually expand the stack by that much
   when delivering signals.  A fair-enough thing to want to test.

   It does this by getting into the signal handler, and then
   recursively invoking the handler by sending itself the signal
   again, until the stack has grown to 4MB from the starting frame
   (main).

   Consequence is: it is essential that we do not disable delivery of
   further signals within the handler itself, else the kernel will
   wait till the handler exits before delivering the next signal, the
   frame will be cleared, the stack will never grow, and we'll be in
   an infinite loop.

   Hence we *must* give the SA_NODEFER flag when setting up the
   handler.
*/

static char *deep;

#define SIZE	(4*1024*1024)

static void handler(int sig)
{
	char here;

	if (&here < deep) {
		printf("PASSED\n");
		exit(0);
	}

	kill(getpid(), SIGUSR1);
}

int main()
{
	struct sigaction sa;

	char here;
	deep = &here - SIZE;

	sa.sa_handler = handler;
#if defined(SA_NODEFER)
	sa.sa_flags = SA_NODEFER;
#endif
	sigemptyset(&sa.sa_mask);
	
	sigaction(SIGUSR1, &sa, NULL);

	kill(getpid(), SIGUSR1);

	printf("FAILED\n");
	exit(1);
}

