On Thu, Aug 09, 2012 at 02:08:50PM +0300, Konstantin Belousov wrote: > Third alternative, which seems to be even better, is to restore > single-threading of the parent for vfork().
I mean this patch. diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 6cb95cd..e59ee21 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -756,7 +756,7 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp, struct thread *td2; struct vmspace *vm2; vm_ooffset_t mem_charged; - int error; + int error, single_threaded; static int curfail; static struct timeval lastfail; #ifdef PROCDESC @@ -815,6 +815,19 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp, } #endif + if (((p1->p_flag & (P_HADTHREADS | P_SYSTEM)) == P_HADTHREADS) && + (flags & RFPPWAIT) != 0) { + PROC_LOCK(p1); + if (thread_single(SINGLE_BOUNDARY)) { + PROC_UNLOCK(p1); + error = ERESTART; + goto fail2; + } + PROC_UNLOCK(p1); + single_threaded = 1; + } else + single_threaded = 0; + mem_charged = 0; vm2 = NULL; if (pages == 0) @@ -945,6 +958,12 @@ fail1: if (vm2 != NULL) vmspace_free(vm2); uma_zfree(proc_zone, newproc); + if (single_threaded) { + PROC_LOCK(p1); + thread_single_end(); + PROC_UNLOCK(p1); + } +fail2: #ifdef PROCDESC if (((flags & RFPROCDESC) != 0) && (fp_procdesc != NULL)) { fdclose(td->td_proc->p_fd, fp_procdesc, *procdescp, td); diff --git a/tools/test/pthread_vfork/pthread_vfork_test.c b/tools/test/pthread_vfork/pthread_vfork_test.c index e004727..88956c2 100644 --- a/tools/test/pthread_vfork/pthread_vfork_test.c +++ b/tools/test/pthread_vfork/pthread_vfork_test.c @@ -29,6 +29,8 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include <sys/types.h> +#include <sys/wait.h> #include <err.h> #include <pthread.h> #include <signal.h> @@ -39,10 +41,11 @@ __FBSDID("$FreeBSD$"); #define NUM_THREADS 100 -void * -vfork_test(void *threadid) +static void * +vfork_test(void *threadid __unused) { - pid_t pid; + pid_t pid, wpid; + int status; for (;;) { pid = vfork(); @@ -50,10 +53,20 @@ vfork_test(void *threadid) _exit(0); else if (pid == -1) err(1, "Failed to vfork"); + else { + wpid = waitpid(pid, &status, 0); + if (wpid == -1) + err(1, "waitpid"); + } } return (NULL); } +static void +sighandler(int signo __unused) +{ +} + /* * This program invokes multiple threads and each thread calls * vfork() system call. @@ -63,19 +76,24 @@ main(void) { pthread_t threads[NUM_THREADS]; struct sigaction reapchildren; + sigset_t sigchld_mask; int rc, t; memset(&reapchildren, 0, sizeof(reapchildren)); - reapchildren.sa_handler = SIG_IGN; - - /* Automatically reap zombies. */ + reapchildren.sa_handler = sighandler; if (sigaction(SIGCHLD, &reapchildren, NULL) == -1) err(1, "Could not sigaction(SIGCHLD)"); + sigemptyset(&sigchld_mask); + sigaddset(&sigchld_mask, SIGCHLD); + if (sigprocmask(SIG_BLOCK, &sigchld_mask, NULL) == -1) + err(1, "sigprocmask"); + for (t = 0; t < NUM_THREADS; t++) { rc = pthread_create(&threads[t], NULL, vfork_test, (void *)t); if (rc) errc(1, rc, "pthread_create"); } + pause(); return (0); }
pgptV1MFHcVI0.pgp
Description: PGP signature