mirror of
https://github.com/ioacademy-jikim/debugging
synced 2025-06-08 16:36:21 +00:00
110 lines
2.5 KiB
C
110 lines
2.5 KiB
C
/* 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;
|
|
}
|
|
|