blob: 8097fb9681c23ae23f8328e732ab623d2945cd1d [file] [log] [blame]
/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
#include "util.h"
#ifndef MADV_WIPEONFORK
#define MADV_WIPEONFORK 18
#endif
#ifndef MADV_KEEPONFORK
#define MADV_KEEPONFORK 19
#endif
int main(void) {
char* page;
pid_t pid;
int status;
size_t page_size = sysconf(_SC_PAGESIZE);
page = mmap(NULL, page_size * 4, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
test_assert(page != MAP_FAILED);
if (0 != madvise(page, 4 * page_size, MADV_WIPEONFORK)) {
atomic_puts("MADV_WIPEONFORK not supported, skipping test.");
atomic_puts("EXIT-SUCCESS");
return 0;
}
test_assert(0 == madvise(page + page_size, page_size, MADV_KEEPONFORK));
test_assert(0 == madvise(page + 3 * page_size, page_size, MADV_KEEPONFORK));
page[0] = 1;
page[page_size] = 1;
page[2 * page_size] = 1;
page[3 * page_size] = 1;
pid = fork();
if (!pid) {
test_assert(page[0] == 0);
test_assert(page[page_size] == 1);
test_assert(page[2 * page_size] == 0);
test_assert(page[3 * page_size] == 1);
atomic_puts("EXIT-SUCCESS");
return 77;
}
test_assert(pid == wait(&status));
test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);
test_assert(0 == madvise(page, 4 * page_size, MADV_DONTFORK));
test_assert(0 == madvise(page, 2 * page_size, MADV_DOFORK));
pid = fork();
if (!pid) {
// This should still be zero, because DONTFORK and WIPEONFORK are tracked
// separately in the kernel.
test_assert(page[0] == 0);
test_assert(page[page_size] == 1);
test_assert(page[2 * page_size] == 1); // This should segfault.
atomic_puts("FAILED: the third page should have been removed.");
return -4;
}
test_assert(pid == wait(&status));
test_assert(WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV);
return 0;
}