1/* This test causes an error in 3.10.1 and earlier versions like so: 2 3==8336== Can't extend stack to 0x4033f98 during signal delivery for thread 2: 4==8336== no stack segment 5 6 The reason was that only AnonC segments were considered as stack 7 segments. */ 8 9#include <assert.h> 10#include <fcntl.h> 11#include <pthread.h> 12#include <setjmp.h> 13#include <signal.h> 14#include <stdio.h> 15#include <stdlib.h> 16#include <unistd.h> 17#include <sys/mman.h> 18#include <sys/stat.h> 19 20static volatile char *lowest_j; 21static jmp_buf goback; 22 23static void sigsegv_handler(int signr) 24{ 25 longjmp(goback, 1); 26} 27 28static void bad_things_till_guard_page(void) 29{ 30 fprintf(stderr, "... doing bad things till guard page\n"); 31 char j = 0; 32 char *p = &j; 33 34 for (;;) { 35 j = j + *p; 36 p = p - 400; 37 lowest_j = p; 38 } 39} 40 41static void say_something(void) 42{ 43 fprintf(stderr, "plugh\n"); 44} 45 46static void *child_func(void *arg) 47{ 48 if (setjmp(goback)) 49 say_something(); 50 else 51 bad_things_till_guard_page(); 52 53 return NULL; 54} 55 56int main(int argc, const char *argv[]) 57{ 58 /* We will discover the thread guard page using SEGV. 59 So, prepare a handler. */ 60 struct sigaction sa; 61 sa.sa_handler = sigsegv_handler; 62 sigemptyset(&sa.sa_mask); 63 sa.sa_flags = 0; 64 if (sigaction(SIGSEGV, &sa, NULL) != 0) 65 perror("sigaction"); 66 67 /* Create a file that will be used as stack for a pthread. */ 68 size_t file_size = 1024 * 1024; 69 const char file_name[] = "FILE"; 70 int fd = open(file_name, O_CREAT|O_WRONLY, 71 S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); 72 assert(fd >= 0); 73 void *p = calloc(file_size, 1); 74 assert(p != 0); 75 int written = write(fd, p, file_size); 76 assert(written == file_size); 77 close(fd); 78 79 /* Create a file-based stack for the child. */ 80 fd = open(file_name, O_CREAT|O_RDWR, 81 S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); 82 assert(fd >= 0); 83 const size_t stack_size = 256 * 1024; 84 assert(stack_size < file_size); 85 void *stack = mmap(NULL, stack_size, PROT_READ|PROT_WRITE, 86 MAP_PRIVATE, fd, 0); 87 assert(stack != (void *)-1); 88 pthread_attr_t attr; 89 pthread_attr_init(&attr); 90 int r = pthread_attr_setstack(&attr, stack, stack_size); 91 assert(r == 0); 92 93 /* Create child run. */ 94 pthread_t child; 95 r = pthread_create(&child, &attr, child_func, NULL); 96 assert(r == 0); 97 r = pthread_join(child, NULL); 98 assert(r == 0); 99 100 /* Remove file */ 101 unlink(file_name); 102 return 0; 103} 104 105