fork fails after nmap with hint address in an unmapped memory region

Stéphane Mbape via cygwin cygwin@cygwin.com
Sun Dec 10 13:30:00 GMT 2017


I used a temporary fix that may give you a hint.

hint_addr = hint_addr - hint_addr % getpagesize(); // temporary fix

I also used it in luajit, which uses a random hint_addr, and everything is fine.

On 09/12/2017 18:29, Brian Inglis wrote:

    On 2017-12-09 08:53, Stéphane Mbape via cygwin wrote:

        Le 09/12/2017 à 16:48, Andrey Repin a écrit :

                While embeding luajit in a c  program, I found myself unable to fork
                processes.
                Investigations prove that it was related to nmap.
                To be accurate, calling nmap with hint address in a unmapped memory
                region will cause all forks to fail with
                "fixup_mmaps_after_fork: ReadProcessMemory failed for MAP_PRIVATE
                address 0x6FFFFFE0000, Win32 error 299"
                There is a sample code below.

            You forgot to mention Cygwin version you're using, and please provide the
            sample as an attach to save people the copy-pasting issues.

        Cygwin version: 2.9.0
        OS: Windows 10
        Arch: 64bit
        The sample was also attached.

    Confirmed reproducible; addr2line does not give anything useful from the
    stackdump, but included raw stackdump below, in case it gives hints.

-------------- next part --------------
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdint.h>
#include <windows.h>

#define MMAP_PROT           (PROT_READ|PROT_WRITE)
#define MMAP_FLAGS_PROBE    (MAP_PRIVATE|MAP_ANONYMOUS)

int main() {
    printf("I am master %d\n", (int) getpid());

    size_t size = ((size_t)128U * (size_t)1024U);
    uintptr_t hint_addr = 0;

    void *p = mmap((void *)hint_addr, size, MMAP_PROT, MMAP_FLAGS_PROBE, -1, 0);
    printf ("nmap() = %p, hint_addr = %p\n", p, (void *) hint_addr);

    uintptr_t addr = (uintptr_t) p;

    munmap(p, size); // make sure there is an unmapped memory

    // hint_addr = addr; // produces no error
    // hint_addr = addr + 1; // produces an error
    hint_addr = hint_addr - hint_addr % getpagesize(); // temporary fix

    p = mmap((void *)hint_addr, size, MMAP_PROT, MMAP_FLAGS_PROBE, -1, 0);
    printf ("nmap() = %p, hint_addr = %p\n", p, (void *) hint_addr);

    pid_t child_pid = fork();

    if (child_pid < 0) {
        perror("fork failed");
    } else if (child_pid == 0) {
        printf("I am worker %d\n", (int) getpid());
        sleep(2);
        printf("worker exiting\n");
        exit(0);
    }

    wait(NULL);

    printf("master exiting\n");
    return 0;
}
-------------- next part --------------

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple


More information about the Cygwin mailing list