svn commit: r254297 - head/lib/libc/stdlib

Peter Wemm peter at FreeBSD.org
Tue Aug 13 20:38:56 UTC 2013


Author: peter
Date: Tue Aug 13 20:38:55 2013
New Revision: 254297
URL: http://svnweb.freebsd.org/changeset/base/254297

Log:
  vfork(2) was listed as deprecated in 1994 (r1573) and was the false
  reports of its impending demise were removed in 2009 (r199257).
  
  However, in 1996 (r16117) system(3) was switched from vfork(2) to
  fork(2) based partly on this.  Switch back to vfork(2).  This has a
  dramatic effect in cases of extreme mmap use - such as excessive
  abuse (500+) of shared libraries.
  
  popen(3) has used vfork(2) for a while.  vfork(2) isn't going anywhere.

Modified:
  head/lib/libc/stdlib/system.c

Modified: head/lib/libc/stdlib/system.c
==============================================================================
--- head/lib/libc/stdlib/system.c	Tue Aug 13 20:33:50 2013	(r254296)
+++ head/lib/libc/stdlib/system.c	Tue Aug 13 20:38:55 2013	(r254297)
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
 #include <signal.h>
 #include <stdlib.h>
 #include <stddef.h>
+#include <string.h>
 #include <unistd.h>
 #include <paths.h>
 #include <errno.h>
@@ -56,37 +57,36 @@ __system(const char *command)
 	if (!command)		/* just checking... */
 		return(1);
 
-	/*
-	 * Ignore SIGINT and SIGQUIT, block SIGCHLD. Remember to save
-	 * existing signal dispositions.
-	 */
-	ign.sa_handler = SIG_IGN;
-	(void)sigemptyset(&ign.sa_mask);
-	ign.sa_flags = 0;
-	(void)_sigaction(SIGINT, &ign, &intact);
-	(void)_sigaction(SIGQUIT, &ign, &quitact);
 	(void)sigemptyset(&newsigblock);
 	(void)sigaddset(&newsigblock, SIGCHLD);
 	(void)_sigprocmask(SIG_BLOCK, &newsigblock, &oldsigblock);
-	switch(pid = fork()) {
+	switch(pid = vfork()) {
 	case -1:			/* error */
-		break;
+		(void)_sigprocmask(SIG_SETMASK, &oldsigblock, NULL);
+		return (-1);
 	case 0:				/* child */
 		/*
 		 * Restore original signal dispositions and exec the command.
 		 */
-		(void)_sigaction(SIGINT, &intact, NULL);
-		(void)_sigaction(SIGQUIT,  &quitact, NULL);
 		(void)_sigprocmask(SIG_SETMASK, &oldsigblock, NULL);
 		execl(_PATH_BSHELL, "sh", "-c", command, (char *)NULL);
 		_exit(127);
-	default:			/* parent */
-		savedpid = pid;
-		do {
-			pid = _wait4(savedpid, &pstat, 0, (struct rusage *)0);
-		} while (pid == -1 && errno == EINTR);
-		break;
 	}
+	/* 
+	 * If we are running means that the child has either completed
+	 * its execve, or has failed.
+	 * Block SIGINT/QUIT because sh -c handles it and wait for
+	 * it to clean up.
+	 */
+	memset(&ign, 0, sizeof(ign));
+	ign.sa_handler = SIG_IGN;
+	(void)sigemptyset(&ign.sa_mask);
+	(void)_sigaction(SIGINT, &ign, &intact);
+	(void)_sigaction(SIGQUIT, &ign, &quitact);
+	savedpid = pid;
+	do {
+		pid = _wait4(savedpid, &pstat, 0, (struct rusage *)0);
+	} while (pid == -1 && errno == EINTR);
 	(void)_sigaction(SIGINT, &intact, NULL);
 	(void)_sigaction(SIGQUIT,  &quitact, NULL);
 	(void)_sigprocmask(SIG_SETMASK, &oldsigblock, NULL);


More information about the svn-src-head mailing list