Module Name:    src
Committed By:   christos
Date:           Wed May 18 03:51:41 UTC 2011

Modified Files:
        src/sys/kern: sys_select.c sys_sig.c
        src/sys/sys: signalvar.h

Log Message:
PR/43625: Mark Davies: Fix pselect(2) to honor the temporary mask. pselect(2)
(and pollts(2)) are similar to sigsuspend(2) in that they temporarily change
the process signal mask and wait for signal delivery. Factor out and share the
code that does this.


To generate a diff of this commit:
cvs rdiff -u -r1.30 -r1.31 src/sys/kern/sys_select.c
cvs rdiff -u -r1.32 -r1.33 src/sys/kern/sys_sig.c
cvs rdiff -u -r1.79 -r1.80 src/sys/sys/signalvar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/sys_select.c
diff -u src/sys/kern/sys_select.c:1.30 src/sys/kern/sys_select.c:1.31
--- src/sys/kern/sys_select.c:1.30	Sat Mar  5 23:41:58 2011
+++ src/sys/kern/sys_select.c	Tue May 17 23:51:41 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: sys_select.c,v 1.30 2011/03/06 04:41:58 rmind Exp $	*/
+/*	$NetBSD: sys_select.c,v 1.31 2011/05/18 03:51:41 christos Exp $	*/
 
 /*-
  * Copyright (c) 2007, 2008, 2009, 2010 The NetBSD Foundation, Inc.
@@ -84,7 +84,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_select.c,v 1.30 2011/03/06 04:41:58 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_select.c,v 1.31 2011/05/18 03:51:41 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -219,10 +219,8 @@
     struct timespec *ts, sigset_t *mask, register_t *retval)
 {
 	lwp_t		* const l = curlwp;
-	proc_t		* const p = l->l_proc;
 	selcluster_t	*sc;
 	kmutex_t	*lock;
-	sigset_t	oldmask;
 	struct timespec	sleepts;
 	int		error, timo;
 
@@ -233,13 +231,7 @@
 
 	if (__predict_false(mask)) {
 		sigminusset(&sigcantmask, mask);
-		mutex_enter(p->p_lock);
-		oldmask = l->l_sigmask;
-		l->l_sigmask = *mask;
-		mutex_exit(p->p_lock);
-	} else {
-		/* XXXgcc */
-		oldmask = l->l_sigmask;
+		sigsuspendsetup(l, mask);
 	}
 
 	sc = curcpu()->ci_data.cpu_selcluster;
@@ -314,12 +306,6 @@
 	}
 	selclear();
 
-	if (__predict_false(mask)) {
-		mutex_enter(p->p_lock);
-		l->l_sigmask = oldmask;
-		mutex_exit(p->p_lock);
-	}
-
 	/* select and poll are not restarted after signals... */
 	if (error == ERESTART)
 		return EINTR;

Index: src/sys/kern/sys_sig.c
diff -u src/sys/kern/sys_sig.c:1.32 src/sys/kern/sys_sig.c:1.33
--- src/sys/kern/sys_sig.c:1.32	Thu Mar  3 15:46:16 2011
+++ src/sys/kern/sys_sig.c	Tue May 17 23:51:41 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: sys_sig.c,v 1.32 2011/03/03 20:46:16 martin Exp $	*/
+/*	$NetBSD: sys_sig.c,v 1.33 2011/05/18 03:51:41 christos Exp $	*/
 
 /*-
  * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_sig.c,v 1.32 2011/03/03 20:46:16 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_sig.c,v 1.33 2011/05/18 03:51:41 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -604,33 +604,39 @@
 	mutex_exit(p->p_lock);
 }
 
-int
-sigsuspend1(struct lwp *l, const sigset_t *ss)
+void
+sigsuspendsetup(struct lwp *l, const sigset_t *ss)
 {
 	struct proc *p = l->l_proc;
 
-	if (ss) {
-		/*
-		 * When returning from sigsuspend, we want
-		 * the old mask to be restored after the
-		 * signal handler has finished.  Thus, we
-		 * save it here and mark the sigctx structure
-		 * to indicate this.
-		 */
-		mutex_enter(p->p_lock);
-		l->l_sigrestore = 1;
-		l->l_sigoldmask = l->l_sigmask;
-		l->l_sigmask = *ss;
-		sigminusset(&sigcantmask, &l->l_sigmask);
+	/*
+	 * When returning from sigsuspend/pselect/pollts, we want
+	 * the old mask to be restored after the
+	 * signal handler has finished.  Thus, we
+	 * save it here and mark the sigctx structure
+	 * to indicate this.
+	 */
+	mutex_enter(p->p_lock);
+	l->l_sigrestore = 1;
+	l->l_sigoldmask = l->l_sigmask;
+	l->l_sigmask = *ss;
+	sigminusset(&sigcantmask, &l->l_sigmask);
 
-		/* Check for pending signals when sleeping. */
-		if (sigispending(l, 0)) {
-			lwp_lock(l);
-			l->l_flag |= LW_PENDSIG;
-			lwp_unlock(l);
-		}
-		mutex_exit(p->p_lock);
+	/* Check for pending signals when sleeping. */
+	if (sigispending(l, 0)) {
+		lwp_lock(l);
+		l->l_flag |= LW_PENDSIG;
+		lwp_unlock(l);
 	}
+	mutex_exit(p->p_lock);
+}
+
+int
+sigsuspend1(struct lwp *l, const sigset_t *ss)
+{
+
+	if (ss)
+		sigsuspendsetup(l, ss);
 
 	while (kpause("pause", true, 0, NULL) == 0)
 		;

Index: src/sys/sys/signalvar.h
diff -u src/sys/sys/signalvar.h:1.79 src/sys/sys/signalvar.h:1.80
--- src/sys/sys/signalvar.h:1.79	Tue Apr 26 20:38:37 2011
+++ src/sys/sys/signalvar.h	Tue May 17 23:51:41 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: signalvar.h,v 1.79 2011/04/27 00:38:37 rmind Exp $	*/
+/*	$NetBSD: signalvar.h,v 1.80 2011/05/18 03:51:41 christos Exp $	*/
 
 /*
  * Copyright (c) 1991, 1993
@@ -148,6 +148,7 @@
 	    struct sigaction *, const void *, int);
 int	sigprocmask1(struct lwp *, int, const sigset_t *, sigset_t *);
 void	sigpending1(struct lwp *, sigset_t *);
+void	sigsuspendsetup(struct lwp *, const sigset_t *);
 int	sigsuspend1(struct lwp *, const sigset_t *);
 int	sigaltstack1(struct lwp *, const struct sigaltstack *,
 	    struct sigaltstack *);

Reply via email to