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