Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 10 Aug 2012 13:13:02 +0300
From:      Konstantin Belousov <kostikbel@gmail.com>
To:        Jilles Tjoelker <jilles@stack.nl>
Cc:        freebsd-hackers@freebsd.org, davidxu@freebsd.org
Subject:   Re: system() using vfork() or posix_spawn() and libthr
Message-ID:  <20120810101302.GF2425@deviant.kiev.zoral.com.ua>
In-Reply-To: <20120809110850.GA2425@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>

next in thread | previous in thread | raw e-mail | index | archive | help

--GLp9dJVi+aaipsRk
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

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 p=
roc **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
=20
+	if (((p1->p_flag & (P_HADTHREADS | P_SYSTEM)) =3D=3D P_HADTHREADS) &&
+	    (flags & RFPPWAIT) !=3D 0) {
+		PROC_LOCK(p1);
+		if (thread_single(SINGLE_BOUNDARY)) {
+			PROC_UNLOCK(p1);
+			error =3D ERESTART;
+			goto fail2;
+		}
+		PROC_UNLOCK(p1);
+		single_threaded =3D 1;
+	} else
+		single_threaded =3D 0;
+
 	mem_charged =3D 0;
 	vm2 =3D NULL;
 	if (pages =3D=3D 0)
@@ -945,6 +958,12 @@ fail1:
 	if (vm2 !=3D 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) !=3D 0) && (fp_procdesc !=3D 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/pth=
read_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$");
=20
+#include <sys/types.h>
+#include <sys/wait.h>
 #include <err.h>
 #include <pthread.h>
 #include <signal.h>
@@ -39,10 +41,11 @@ __FBSDID("$FreeBSD$");
=20
 #define NUM_THREADS 100
=20
-void *
-vfork_test(void *threadid)
+static void *
+vfork_test(void *threadid __unused)
 {
-	pid_t pid;
+	pid_t pid, wpid;
+	int status;
=20
 	for (;;) {
 		pid =3D vfork();
@@ -50,10 +53,20 @@ vfork_test(void *threadid)
 			_exit(0);
 		else if (pid =3D=3D -1)
 			err(1, "Failed to vfork");
+		else {
+			wpid =3D waitpid(pid, &status, 0);
+			if (wpid =3D=3D -1)
+				err(1, "waitpid");
+		}
 	}
 	return (NULL);
 }
=20
+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;
=20
 	memset(&reapchildren, 0, sizeof(reapchildren));
-	reapchildren.sa_handler =3D SIG_IGN;
-
-	/* Automatically reap zombies. */
+	reapchildren.sa_handler =3D sighandler;
 	if (sigaction(SIGCHLD, &reapchildren, NULL) =3D=3D -1)
 		err(1, "Could not sigaction(SIGCHLD)");
=20
+	sigemptyset(&sigchld_mask);
+	sigaddset(&sigchld_mask, SIGCHLD);
+	if (sigprocmask(SIG_BLOCK, &sigchld_mask, NULL) =3D=3D -1)
+		err(1, "sigprocmask");
+
 	for (t =3D 0; t < NUM_THREADS; t++) {
 		rc =3D pthread_create(&threads[t], NULL, vfork_test, (void *)t);
 		if (rc)
 			errc(1, rc, "pthread_create");
 	}
+	pause();
 	return (0);
 }

--GLp9dJVi+aaipsRk
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (FreeBSD)

iEYEARECAAYFAlAk3q4ACgkQC3+MBN1Mb4g29QCghHodkIf2zunuCoeJlrsux7QN
fP8AoJ/taKj2h5VQAco2vg/NY90ZmyZW
=c6ZU
-----END PGP SIGNATURE-----

--GLp9dJVi+aaipsRk--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120810101302.GF2425>