summaryrefslogtreecommitdiff
path: root/lib/libpthread
diff options
context:
space:
mode:
authornathanw <nathanw@NetBSD.org>2003-03-14 22:27:34 +0000
committernathanw <nathanw@NetBSD.org>2003-03-14 22:27:34 +0000
commita25b9285d9bfa70dba79b9da65fa5d397ac1e3c8 (patch)
treec7af9f3995562d474e456d930135d86f0a426eb2 /lib/libpthread
parent022a762c83e164249cf5da1ec93df6f111ab5e3f (diff)
Add a wrapper for the execve() system call that arranges for the current
thread sigal mask to be propagated into the new process image.
Diffstat (limited to 'lib/libpthread')
-rw-r--r--lib/libpthread/pthread_sig.c49
1 files changed, 47 insertions, 2 deletions
diff --git a/lib/libpthread/pthread_sig.c b/lib/libpthread/pthread_sig.c
index c3b1aa3283a..07cfa0bc3b5 100644
--- a/lib/libpthread/pthread_sig.c
+++ b/lib/libpthread/pthread_sig.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pthread_sig.c,v 1.11 2003/03/08 08:03:35 lukem Exp $ */
+/* $NetBSD: pthread_sig.c,v 1.12 2003/03/14 22:27:34 nathanw Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread_sig.c,v 1.11 2003/03/08 08:03:35 lukem Exp $");
+__RCSID("$NetBSD: pthread_sig.c,v 1.12 2003/03/14 22:27:34 nathanw Exp $");
/* We're interposing a specific version of the signal interface. */
#define __LIBC12_SOURCE__
@@ -105,7 +105,10 @@ pthread__signal_tramp(int, int, void (*)(int, int, struct sigcontext *),
static int firstsig(const sigset_t *);
+int _sys_execve(const char *, char *const [], char *const []);
+
__strong_alias(__libc_thr_sigsetmask,pthread_sigmask)
+__strong_alias(__exeve,execve)
void
pthread__signal_init(void)
@@ -893,3 +896,45 @@ pthread__signal_tramp(int sig, int code,
/*NOTREACHED*//*CONSTCOND*/
assert(0);
}
+
+/*
+ * The execve() system call and the libc exec*() calls that use it are
+ * specified to propagate the signal mask of the current thread to the
+ * initial thread of the new process image. Since thread signal masks
+ * are maintained in userlevel, this wrapper is necessary to give the
+ * kernel the correct value.
+ */
+int
+execve(const char *path, char *const argv[], char *const envp[])
+{
+ pthread_t self;
+ int ret;
+
+ self = pthread__self();
+
+ /*
+ * Don't acquire pt_process_siglock, even though it seems like
+ * the right thing to do. The most common reason to be here is
+ * that we're on the child side of a fork() or vfork()
+ * call. In either case, another thread could have held
+ * pt_process_siglock at the moment of forking, and acquiring
+ * it here would cause us to deadlock. Additionally, in the
+ * case of vfork(), acquiring the lock here would cause it to
+ * be locked in the parent's address space and cause a
+ * deadlock there the next time a signal routine is called.
+ *
+ * The remaining case is where a live multithreaded program
+ * calls exec*() from one of several threads with no explicit
+ * synchronization. It may get the wrong process sigmask in
+ * the new process image if another thread executes a signal
+ * routine between the sigprocmask and the _sys_execve()
+ * call. I don't have much sympathy for such a program.
+ */
+ __sigprocmask14(SIG_SETMASK, &self->pt_sigmask, NULL);
+ ret = _sys_execve(path, argv, envp);
+
+ /* Normally, we shouldn't get here; this is an error condition. */
+ __sigprocmask14(SIG_SETMASK, &pt_process_sigmask, NULL);
+
+ return ret;
+}