summaryrefslogtreecommitdiff
path: root/lib/libc/stdlib
diff options
context:
space:
mode:
authornathanw <nathanw@NetBSD.org>2003-03-04 19:44:09 +0000
committernathanw <nathanw@NetBSD.org>2003-03-04 19:44:09 +0000
commitf60f35f3abdd92d76d383ac4dd83273d2be1225b (patch)
treec6b9b847006379eb901818b8c74701ca2029761c /lib/libc/stdlib
parent2ea5d53fe34798182fe2bd28c6f3d0af48bd63a3 (diff)
Don't acquire __environ_lock around exec*() calls; nothing requires
that these calls be thread-safe with respect to the environment, and it causes serious problems for threaded applications which call vfork() and exec*() (including indirectly, via popen() or system()). Acquire and release __environ_lock in the parent in popen() and system() to play safe and provide the child with a stable environment. __environ_lock should also have an atfork() handler; still under development.
Diffstat (limited to 'lib/libc/stdlib')
-rw-r--r--lib/libc/stdlib/system.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/lib/libc/stdlib/system.c b/lib/libc/stdlib/system.c
index 26179d0adb8..fb78c87cd9e 100644
--- a/lib/libc/stdlib/system.c
+++ b/lib/libc/stdlib/system.c
@@ -1,4 +1,4 @@
-/* $NetBSD: system.c,v 1.17 2001/10/31 13:31:26 kleink Exp $ */
+/* $NetBSD: system.c,v 1.18 2003/03/04 19:44:10 nathanw Exp $ */
/*
* Copyright (c) 1988, 1993
@@ -38,7 +38,7 @@
#if 0
static char sccsid[] = "@(#)system.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD: system.c,v 1.17 2001/10/31 13:31:26 kleink Exp $");
+__RCSID("$NetBSD: system.c,v 1.18 2003/03/04 19:44:10 nathanw Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -50,7 +50,11 @@ __RCSID("$NetBSD: system.c,v 1.17 2001/10/31 13:31:26 kleink Exp $");
#include <stdlib.h>
#include <unistd.h>
#include <paths.h>
+#include "reentrant.h"
+#ifdef _REENTRANT
+extern rwlock_t __environ_lock;
+#endif
extern char **environ;
int
@@ -80,8 +84,10 @@ system(command)
if (sigprocmask(SIG_BLOCK, &nmask, &omask) == -1)
return -1;
+ rwlock_rdlock(&__environ_lock);
switch(pid = vfork()) {
case -1: /* error */
+ rwlock_unlock(&__environ_lock);
sigaction(SIGINT, &intsa, NULL);
sigaction(SIGQUIT, &quitsa, NULL);
(void)sigprocmask(SIG_SETMASK, &omask, NULL);
@@ -93,6 +99,7 @@ system(command)
execve(_PATH_BSHELL, argp, environ);
_exit(127);
}
+ rwlock_unlock(&__environ_lock);
while (waitpid(pid, &pstat, 0) == -1) {
if (errno != EINTR) {