Re: using of fork() in multithreaded application
Taylor R Campbell <[email protected]>
| Newsgroups | gmane.os.netbsd.devel.kernel |
|---|---|
| Message-ID | <[email protected]> |
> Date: Wed, 22 Jan 2025 16:47:13 +0100 > From: Peter Skvarka <[email protected]> > > 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).
hack.c
(text/plain, 1.2 KB)
#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;
}