Date: Sun, 12 Aug 2012 08:11:29 +0800 From: David Xu <listlog2011@gmail.com> To: Konstantin Belousov <kostikbel@gmail.com> Cc: freebsd-hackers@freebsd.org, davidxu@freebsd.org, Jilles Tjoelker <jilles@stack.nl> Subject: Re: system() using vfork() or posix_spawn() and libthr Message-ID: <5026F4B1.5030000@gmail.com> In-Reply-To: <20120810101302.GF2425@deviant.kiev.zoral.com.ua> References: <20120730102408.GA19983@stack.nl> <20120730105303.GU2676@deviant.kiev.zoral.com.ua> <20120805215432.GA28704@stack.nl> <20120806082535.GI2676@deviant.kiev.zoral.com.ua> <20120809105648.GA79814@stack.nl> <20120809110850.GA2425@deviant.kiev.zoral.com.ua> <20120810101302.GF2425@deviant.kiev.zoral.com.ua>
next in thread | previous in thread | raw e-mail | index | archive | help
On 2012/08/10 18:13, Konstantin Belousov wrote: > 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(). single-threading is slow for large threaded process, don't know if it is necessary for vfork(), POSIX says nothing about threaded process. > 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); > }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?5026F4B1.5030000>