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