/* This test causes an error in 3.10.1 and earlier versions like so: ==8336== Can't extend stack to 0x4033f98 during signal delivery for thread 2: ==8336== no stack segment The reason was that only AnonC segments were considered as stack segments. */ #include <sys/mman.h> #include <sys/stat.h> #include <stdio.h> #include <pthread.h> #include <string.h> #include <stdlib.h> #include <assert.h> #include <setjmp.h> #include <signal.h> #include <fcntl.h> #include <unistd.h> static volatile char *lowest_j; static jmp_buf goback; static void sigsegv_handler(int signr) { longjmp(goback, 1); } static void bad_things_till_guard_page(void) { fprintf(stderr, "... doing bad things till guard page\n"); char j = 0; char *p = &j; for (;;) { j = j + *p; p = p - 400; lowest_j = p; } } static void say_something(void) { fprintf(stderr, "plugh\n"); } static void* child_func ( void* arg ) { if (setjmp(goback)) { say_something(); } else bad_things_till_guard_page(); return NULL; } int main(int argc, const char** argv) { int r, fd; /* We will discover the thread guard page using SEGV. So, prepare an handler. */ struct sigaction sa; sa.sa_handler = sigsegv_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; if (sigaction (SIGSEGV, &sa, NULL) != 0) perror("sigaction"); pthread_t child; /* Create a file that will be used as stack for a pthread. */ const size_t file_size = 1024 * 1024; const char file_name[] = "FILE"; fd = open(file_name, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); assert(fd > 0); void *p = malloc(file_size); assert(p != 0); memset(p, 0, file_size); int written = write(fd, p, file_size); assert(written == file_size); close(fd); /* Create a file-based stack for the child */ fd = open(file_name, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); assert(fd > 0); const size_t stack_size = 256 * 1024; assert(stack_size < file_size); void *stack = mmap(NULL, stack_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); assert(stack != (void *)-1); pthread_attr_t attr; pthread_attr_init(&attr); r = pthread_attr_setstack(&attr, stack, stack_size); assert(r == 0); /* Create child run */ r = pthread_create(&child, &attr, child_func, NULL); assert(r == 0); r = pthread_join(child, NULL); assert(r == 0); /* Remove file */ unlink(file_name); return 0; }