> Date: Wed, 22 Jan 2025 16:47:13 +0100 > From: Peter Skvarka <p...@softinengines.com> > > On my NetBSD 10.1 I am trying to run multithreaded application where > first are created several threads and then is called fork() from main > thread. > Forked child then calls execvp() . > Passed command line (in argv argument) is "gcc", "-dumpversion". > > Application freezes because it waits for finishing child and ps -auxd > shows child process "(gcc)" > with flag zombie. > > I have two questions: > Is safe using of fork() in NetBSD 10.1 in mutlithreaded application ?
Generally yes, with the caveat that it is difficult for applications to use correctly. For example, if you have any application-specific locks, you usually have to take them carefully in a pthread_atfork handler to avoid deadlock in the child. Do you have a minimal reproducer for the unexpected behaviour you're seeing? I just tried with the attached program and it worked fine. $ ./hack 10.5.0 thread ran $ > Does NetBSD 10.1 support "set follow-fork-mode child" when used > /usr/bin/gdb ? I can step through source code of forked child only > on-two lines not more. Not sure offhand if it works, but if it doesn't work it's probably a bug that should be reported separately (https://gnats.NetBSD.org).
#include <sys/wait.h> #include <err.h> #include <pthread.h> #include <stdio.h> #include <unistd.h> pthread_mutex_t m; void * runthread(void *cookie) { int error; if ((error = pthread_mutex_lock(&m)) != 0) errc(1, error, "pthread_mutex_lock"); printf("thread ran\n"); if ((error = pthread_mutex_unlock(&m)) != 0) errc(1, error, "pthread_mutex_lock"); return NULL; } int main(void) { pthread_t t; pid_t pid, child; int error; if ((error = pthread_mutex_init(&m, NULL)) != 0) errc(1, error, "pthread_mutex_init"); if ((error = pthread_mutex_lock(&m)) != 0) errc(1, error, "pthread_mutex_lock"); if ((error = pthread_create(&t, NULL, &runthread, NULL)) != 0) errc(1, error, "pthread_create"); pid = fork(); switch (pid) { case -1: err(1, "fork"); case 0: execvp("gcc", (char *[]){"gcc", "-dumpversion", NULL}); err(1, "execvp"); default: break; } if ((child = waitpid(pid, NULL, 0)) == -1) err(1, "waitpid"); if (child != pid) { errx(1, "waitpid returned %ld, expected %ld", (long)child, (long)pid); } if ((error = pthread_mutex_unlock(&m)) != 0) errc(1, error, "pthread_mutex_lock"); if ((error = pthread_join(t, NULL)) != 0) errc(1, error, "pthread_join"); return 0; }