> 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;
}

Reply via email to