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