• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
20 static volatile char *lowest_j;
21 static jmp_buf goback;
22 
sigsegv_handler(int signr)23 static void sigsegv_handler(int signr)
24 {
25    longjmp(goback, 1);
26 }
27 
bad_things_till_guard_page(void)28 static 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 
say_something(void)41 static void say_something(void)
42 {
43   fprintf(stderr, "plugh\n");
44 }
45 
child_func(void * arg)46 static 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 
main(int argc,const char * argv[])56 int 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