From owner-svn-src-stable-8@FreeBSD.ORG Sat Dec 19 11:14:00 2009 Return-Path: Delivered-To: svn-src-stable-8@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 52F4610656C3; Sat, 19 Dec 2009 11:14:00 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 405588FC1F; Sat, 19 Dec 2009 11:14:00 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id nBJBE0Ya031367; Sat, 19 Dec 2009 11:14:00 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id nBJBE0lT031362; Sat, 19 Dec 2009 11:14:00 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <200912191114.nBJBE0lT031362@svn.freebsd.org> From: Konstantin Belousov Date: Sat, 19 Dec 2009 11:14:00 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r200721 - in stable/8/sys: compat/freebsd32 kern sys X-BeenThere: svn-src-stable-8@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 8-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 19 Dec 2009 11:14:00 -0000 Author: kib Date: Sat Dec 19 11:13:59 2009 New Revision: 200721 URL: http://svn.freebsd.org/changeset/base/200721 Log: MFC r198506: In kern_sigsuspend(), manipulate thread signal mask using kern_sigprocmask(). Also, do cursig/postsig loop immediately after waiting for signal, repeating the wait if wakeup was spurious due to race with other thread fetching signal from the process queue before us. MFC r199136: Use cpu_set_syscall_retval(9) to set syscall result, and return EJUSTRETURN from kern_sigsuspend() to prevent syscall return code from modifying wrong frame. Take care of possibility that pending SIGCONT might be cancelled by SIGSTOP, causing postsig() not to deliver any catched signal. Modified: stable/8/sys/compat/freebsd32/freebsd32_misc.c stable/8/sys/kern/kern_sig.c stable/8/sys/sys/signalvar.h stable/8/sys/sys/syscallsubr.h Directory Properties: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/xen/xenpci/ (props changed) Modified: stable/8/sys/compat/freebsd32/freebsd32_misc.c ============================================================================== --- stable/8/sys/compat/freebsd32/freebsd32_misc.c Sat Dec 19 11:11:57 2009 (r200720) +++ stable/8/sys/compat/freebsd32/freebsd32_misc.c Sat Dec 19 11:13:59 2009 (r200721) @@ -2579,21 +2579,10 @@ int ofreebsd32_sigsuspend(struct thread *td, struct ofreebsd32_sigsuspend_args *uap) { - struct proc *p = td->td_proc; sigset_t mask; - PROC_LOCK(p); - td->td_oldsigmask = td->td_sigmask; - td->td_pflags |= TDP_OLDMASK; OSIG2SIG(uap->mask, mask); - SIG_CANTMASK(mask); - SIGSETLO(td->td_sigmask, mask); - signotify(td); - while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0) - /* void */; - PROC_UNLOCK(p); - /* always return EINTR rather than ERESTART... */ - return (EINTR); + return (kern_sigsuspend(td, mask)); } struct sigstack32 { Modified: stable/8/sys/kern/kern_sig.c ============================================================================== --- stable/8/sys/kern/kern_sig.c Sat Dec 19 11:11:57 2009 (r200720) +++ stable/8/sys/kern/kern_sig.c Sat Dec 19 11:13:59 2009 (r200721) @@ -966,14 +966,15 @@ execsigs(struct proc *p) */ int kern_sigprocmask(struct thread *td, int how, sigset_t *set, sigset_t *oset, - int old) + int flags) { sigset_t new_block, oset1; struct proc *p; int error; p = td->td_proc; - PROC_LOCK(p); + if (!(flags & SIGPROCMASK_PROC_LOCKED)) + PROC_LOCK(p); if (oset != NULL) *oset = td->td_sigmask; @@ -995,7 +996,7 @@ kern_sigprocmask(struct thread *td, int case SIG_SETMASK: SIG_CANTMASK(*set); oset1 = td->td_sigmask; - if (old) + if (flags & SIGPROCMASK_OLD) SIGSETLO(td->td_sigmask, *set); else td->td_sigmask = *set; @@ -1021,7 +1022,8 @@ kern_sigprocmask(struct thread *td, int if (p->p_numthreads != 1) reschedule_signals(p, new_block); - PROC_UNLOCK(p); + if (!(flags & SIGPROCMASK_PROC_LOCKED)) + PROC_UNLOCK(p); return (error); } @@ -1454,6 +1456,7 @@ int kern_sigsuspend(struct thread *td, sigset_t mask) { struct proc *p = td->td_proc; + int has_sig, sig; /* * When returning from sigsuspend, we want @@ -1463,16 +1466,29 @@ kern_sigsuspend(struct thread *td, sigse * to indicate this. */ PROC_LOCK(p); - td->td_oldsigmask = td->td_sigmask; + kern_sigprocmask(td, SIG_SETMASK, &mask, &td->td_oldsigmask, + SIGPROCMASK_PROC_LOCKED); td->td_pflags |= TDP_OLDMASK; - SIG_CANTMASK(mask); - td->td_sigmask = mask; - signotify(td); - while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "pause", 0) == 0) - /* void */; + + /* + * Process signals now. Otherwise, we can get spurious wakeup + * due to signal entered process queue, but delivered to other + * thread. But sigsuspend should return only on signal + * delivery. + */ + cpu_set_syscall_retval(td, EINTR); + for (has_sig = 0; !has_sig;) { + while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "pause", + 0) == 0) + /* void */; + thread_suspend_check(0); + mtx_lock(&p->p_sigacts->ps_mtx); + while ((sig = cursig(td, SIG_STOP_ALLOWED)) != 0) + has_sig += postsig(sig); + mtx_unlock(&p->p_sigacts->ps_mtx); + } PROC_UNLOCK(p); - /* always return EINTR rather than ERESTART... */ - return (EINTR); + return (EJUSTRETURN); } #ifdef COMPAT_43 /* XXX - COMPAT_FBSD3 */ @@ -1491,21 +1507,10 @@ osigsuspend(td, uap) struct thread *td; struct osigsuspend_args *uap; { - struct proc *p = td->td_proc; sigset_t mask; - PROC_LOCK(p); - td->td_oldsigmask = td->td_sigmask; - td->td_pflags |= TDP_OLDMASK; OSIG2SIG(uap->mask, mask); - SIG_CANTMASK(mask); - SIGSETLO(td->td_sigmask, mask); - signotify(td); - while (msleep(&p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0) - /* void */; - PROC_UNLOCK(p); - /* always return EINTR rather than ERESTART... */ - return (EINTR); + return (kern_sigsuspend(td, mask)); } #endif /* COMPAT_43 */ @@ -2662,7 +2667,7 @@ thread_stopped(struct proc *p) * Take the action for the specified signal * from the current set of pending signals. */ -void +int postsig(sig) register int sig; { @@ -2681,7 +2686,7 @@ postsig(sig) ksiginfo_init(&ksi); if (sigqueue_get(&td->td_sigqueue, sig, &ksi) == 0 && sigqueue_get(&p->p_sigqueue, sig, &ksi) == 0) - return; + return (0); ksi.ksi_signo = sig; if (ksi.ksi_code == SI_TIMER) itimer_accept(p, ksi.ksi_timerid, &ksi); @@ -2747,6 +2752,7 @@ postsig(sig) } (*p->p_sysent->sv_sendsig)(action, &ksi, &returnmask); } + return (1); } /* Modified: stable/8/sys/sys/signalvar.h ============================================================================== --- stable/8/sys/sys/signalvar.h Sat Dec 19 11:11:57 2009 (r200720) +++ stable/8/sys/sys/signalvar.h Sat Dec 19 11:13:59 2009 (r200721) @@ -316,6 +316,10 @@ extern int kern_logsigexit; /* Sysctl va #define SIG_STOP_ALLOWED 100 #define SIG_STOP_NOT_ALLOWED 101 +/* flags for kern_sigprocmask */ +#define SIGPROCMASK_OLD 0x0001 +#define SIGPROCMASK_PROC_LOCKED 0x0002 + /* * Machine-independent functions: */ @@ -325,7 +329,7 @@ void gsignal(int pgid, int sig); void killproc(struct proc *p, char *why); void pgsigio(struct sigio **, int signum, int checkctty); void pgsignal(struct pgrp *pgrp, int sig, int checkctty); -void postsig(int sig); +int postsig(int sig); void psignal(struct proc *p, int sig); int psignal_event(struct proc *p, struct sigevent *, ksiginfo_t *); struct sigacts *sigacts_alloc(void); @@ -359,7 +363,8 @@ void sigqueue_delete_stopmask_proc(struc void sigqueue_take(ksiginfo_t *ksi); int kern_sigtimedwait(struct thread *, sigset_t, ksiginfo_t *, struct timespec *); - +int kern_sigprocmask(struct thread *td, int how, + sigset_t *set, sigset_t *oset, int flags); /* * Machine-dependent functions: */ Modified: stable/8/sys/sys/syscallsubr.h ============================================================================== --- stable/8/sys/sys/syscallsubr.h Sat Dec 19 11:11:57 2009 (r200720) +++ stable/8/sys/sys/syscallsubr.h Sat Dec 19 11:13:59 2009 (r200721) @@ -190,8 +190,6 @@ int kern_shmctl(struct thread *td, int s int kern_sigaction(struct thread *td, int sig, struct sigaction *act, struct sigaction *oact, int flags); int kern_sigaltstack(struct thread *td, stack_t *ss, stack_t *oss); -int kern_sigprocmask(struct thread *td, int how, - sigset_t *set, sigset_t *oset, int old); int kern_sigsuspend(struct thread *td, sigset_t mask); int kern_stat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp);