Sending signals internally such as from with abort or pthread_kill goes to the wrong process and gives errors. See the code below. I know vfork is hard to support but as of now posix_spawn simply isn't a mature enough replacement. #define _GNU_SOURCE #include <assert.h> #include <sched.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <sys/mman.h> #include <sys/wait.h> #include <unistd.h> static int fork_routine(void *args); static size_t small_stack_size(void); int main(void) { size_t page_size = sysconf(_SC_PAGE_SIZE); size_t stack_size = small_stack_size(); void *stack = mmap(0, stack_size + 2U * page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK | MAP_GROWSDOWN, -1, 0); if (MAP_FAILED == stack) { perror("mmap"); return EXIT_FAILURE; } if (-1 == mprotect(stack, page_size, PROT_NONE)) { perror("mprotect"); return EXIT_FAILURE; } if (-1 == mprotect(((char *)stack) + page_size + stack_size, page_size, PROT_NONE)) { perror("mprotect"); return EXIT_FAILURE; } fprintf(stderr, "before fork\n"); pid_t child = clone(fork_routine, ((char *)stack) + page_size + stack_size, SIGCHLD | CLONE_VM | CLONE_VFORK, 0); if (-1 == child) { perror("clone"); return EXIT_FAILURE; } siginfo_t info; if (-1 == waitid(P_PID, child, &info, WEXITED)) { perror("waitid"); return EXIT_FAILURE; } fprintf(stderr, "out of fork: %i\n", getpid()); getchar(); abort(); return EXIT_SUCCESS; } static int fork_routine(void *args) { write(STDERR_FILENO, "in fork\n", sizeof "in fork\n" - 1U); _Exit(EXIT_SUCCESS); } static size_t small_stack_size(void) { long maybe_page_size = sysconf(_SC_PAGE_SIZE); assert(maybe_page_size >= 0); long maybe_stack_min_size = sysconf(_SC_THREAD_STACK_MIN); assert(maybe_stack_min_size >= 0); size_t page_size = maybe_page_size; size_t stack_min_size = maybe_stack_min_size; return stack_min_size + 3U * page_size; }
fork_routine does not set up a glibc thread descriptor, and calling write and _Exit corrupts the main thread descriptor. This means that the raise call inside abort uses the wrong PID. This is not a bug in glibc. If you call clone directly, you need to make sure that you take care of the thread descriptor situation in some way.
(In reply to Florian Weimer from comment #1) > fork_routine does not set up a glibc thread descriptor, and calling write > and _Exit corrupts the main thread descriptor. This means that the raise > call inside abort uses the wrong PID. > > This is not a bug in glibc. If you call clone directly, you need to make > sure that you take care of the thread descriptor situation in some way. Why even expose clone if you are not going to support it? I would be willing to accept that only execve and _Exit are supported system calls though I guess. That would be very sparse but proportionate to how vfork is usually used.
There are use cases which are valid (if the appropriate flags are specified). We cannot support execve because it needs to set errno on failure, so there has to be a valid thread descriptor.
(In reply to Florian Weimer from comment #3) > There are use cases which are valid (if the appropriate flags are > specified). We cannot support execve because it needs to set errno on > failure, so there has to be a valid thread descriptor. I see. I shall look into alternate ways of accomplishing what I want. The whole reason I wanted to use clone with CLONE_VM is so that I could do a vfork with CLONE_UNTRACED. Thank you for your time.