Skip site navigation (1)Skip section navigation (2)
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>