summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger A. Faulkner <Roger.Faulkner@Sun.COM>2009-04-16 15:36:18 -0700
committerRoger A. Faulkner <Roger.Faulkner@Sun.COM>2009-04-16 15:36:18 -0700
commit9524a69f24734e80c50bfc33c4f1bce173d465a1 (patch)
treed9d772eca43402eff175e4aa1c2efc76b629e868
parent6075fa3de0c83fd23d9e870137abc5f442e9eee2 (diff)
downloadillumos-gate-9524a69f24734e80c50bfc33c4f1bce173d465a1.tar.gz
6565817 sigwait can't wait for SIGTSTP
-rw-r--r--usr/src/uts/common/os/sig.c27
-rw-r--r--usr/src/uts/common/sys/thread.h1
-rw-r--r--usr/src/uts/common/syscall/sigtimedwait.c23
3 files changed, 29 insertions, 22 deletions
diff --git a/usr/src/uts/common/os/sig.c b/usr/src/uts/common/os/sig.c
index 8044529f83..454b9e600f 100644
--- a/usr/src/uts/common/os/sig.c
+++ b/usr/src/uts/common/os/sig.c
@@ -20,16 +20,13 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/param.h>
#include <sys/types.h>
#include <sys/bitmap.h>
@@ -146,6 +143,7 @@ signal_is_blocked(kthread_t *t, int sig)
* the process is single-threaded
* the signal is not being traced by /proc
* the signal is not blocked by the process
+ * the signal is not being accepted via sigwait()
*/
static int
sig_discardable(proc_t *p, int sig)
@@ -156,7 +154,8 @@ sig_discardable(proc_t *p, int sig)
(sigismember(&p->p_ignore, sig) && /* signal is ignored */
t->t_forw == t && /* and single-threaded */
!tracing(p, sig) && /* and no /proc tracing */
- !signal_is_blocked(t, sig))); /* and signal not blocked */
+ !signal_is_blocked(t, sig) && /* and signal not blocked */
+ !sigismember(&t->t_sigwait, sig))); /* and not being accepted */
}
/*
@@ -474,6 +473,7 @@ issig_justlooking(void)
for (sig = 1; sig < NSIG; sig++) {
if (sigismember(&set, sig) &&
(tracing(p, sig) ||
+ sigismember(&t->t_sigwait, sig) ||
!sigismember(&p->p_ignore, sig))) {
/*
* Don't promote a signal that will stop
@@ -622,13 +622,19 @@ issig_forreal(void)
* signal; we cancel lwp->lwp_cursig temporarily before
* calling isjobstop(). The current signal may be reset
* by a debugger while we are stopped in isjobstop().
+ *
+ * If the current thread is accepting the signal
+ * (via sigwait(), sigwaitinfo(), or sigtimedwait()),
+ * we allow the signal to be accepted, even if it is
+ * being ignored, and without causing a job control stop.
*/
if ((sig = lwp->lwp_cursig) != 0) {
ext = lwp->lwp_extsig;
lwp->lwp_cursig = 0;
lwp->lwp_extsig = 0;
- if (!sigismember(&p->p_ignore, sig) &&
- !isjobstop(sig)) {
+ if (sigismember(&t->t_sigwait, sig) ||
+ (!sigismember(&p->p_ignore, sig) &&
+ !isjobstop(sig))) {
if (p->p_flag & (SEXITLWPS|SKILLED)) {
sig = SIGKILL;
ext = (p->p_flag & SEXTKILLED) != 0;
@@ -675,14 +681,12 @@ issig_forreal(void)
* then the signals pending for the process as a whole.
*/
for (;;) {
- k_sigset_t tsig;
-
- tsig = t->t_sig;
- if ((sig = fsig(&tsig, t)) != 0) {
+ if ((sig = fsig(&t->t_sig, t)) != 0) {
if (sig == SIGCLD)
sigcld_found = 1;
toproc = 0;
if (tracing(p, sig) ||
+ sigismember(&t->t_sigwait, sig) ||
!sigismember(&p->p_ignore, sig)) {
if (sigismember(&t->t_extsig, sig))
ext = 1;
@@ -696,6 +700,7 @@ issig_forreal(void)
sigcld_found = 1;
toproc = 1;
if (tracing(p, sig) ||
+ sigismember(&t->t_sigwait, sig) ||
!sigismember(&p->p_ignore, sig)) {
if (sigismember(&p->p_extsig, sig))
ext = 1;
diff --git a/usr/src/uts/common/sys/thread.h b/usr/src/uts/common/sys/thread.h
index 6d112ef065..bb2502679a 100644
--- a/usr/src/uts/common/sys/thread.h
+++ b/usr/src/uts/common/sys/thread.h
@@ -163,6 +163,7 @@ typedef struct _kthread {
k_sigset_t t_sig; /* signals pending to this process */
k_sigset_t t_extsig; /* signals sent from another contract */
k_sigset_t t_hold; /* hold signal bit mask */
+ k_sigset_t t_sigwait; /* sigtimedwait() is accepting these */
struct _kthread *t_forw; /* process's forward thread link */
struct _kthread *t_back; /* process's backward thread link */
struct _kthread *t_thlink; /* tid (lwpid) lookup hash link */
diff --git a/usr/src/uts/common/syscall/sigtimedwait.c b/usr/src/uts/common/syscall/sigtimedwait.c
index ad4d79b763..3740fd5d10 100644
--- a/usr/src/uts/common/syscall/sigtimedwait.c
+++ b/usr/src/uts/common/syscall/sigtimedwait.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,13 +18,12 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/param.h>
#include <sys/types.h>
#include <sys/bitmap.h>
@@ -95,7 +93,6 @@ int
sigtimedwait(sigset_t *setp, siginfo_t *siginfop, timespec_t *timeoutp)
{
sigset_t set;
- k_sigset_t kset;
k_sigset_t oldmask;
kthread_t *t = curthread;
klwp_t *lwp = ttolwp(t);
@@ -135,8 +132,8 @@ sigtimedwait(sigset_t *setp, siginfo_t *siginfop, timespec_t *timeoutp)
}
if (copyin(setp, &set, sizeof (set)))
return (set_errno(EFAULT));
- sigutok(&set, &kset);
- if (sigisempty(&kset))
+ sigutok(&set, &t->t_sigwait);
+ if (sigisempty(&t->t_sigwait))
return (set_errno(EINVAL));
mutex_enter(&p->p_lock);
@@ -146,7 +143,7 @@ sigtimedwait(sigset_t *setp, siginfo_t *siginfop, timespec_t *timeoutp)
*/
schedctl_finish_sigblock(t);
oldmask = t->t_hold;
- sigdiffset(&t->t_hold, &kset);
+ sigdiffset(&t->t_hold, &t->t_sigwait);
/*
* Wait until we take a signal or until
@@ -166,18 +163,21 @@ sigtimedwait(sigset_t *setp, siginfo_t *siginfop, timespec_t *timeoutp)
if (error) {
mutex_exit(&p->p_lock);
+ sigemptyset(&t->t_sigwait);
return (set_errno(error)); /* timer expired */
}
/*
* Don't bother with signal if it is not in request set.
*/
- if (lwp->lwp_cursig == 0 || !sigismember(&kset, lwp->lwp_cursig)) {
+ if (lwp->lwp_cursig == 0 ||
+ !sigismember(&t->t_sigwait, lwp->lwp_cursig)) {
mutex_exit(&p->p_lock);
/*
* lwp_cursig is zero if pokelwps() awakened cv_wait_sig().
* This happens if some other thread in this process called
* forkall() or exit().
*/
+ sigemptyset(&t->t_sigwait);
return (set_errno(EINTR));
}
@@ -203,5 +203,6 @@ sigtimedwait(sigset_t *setp, siginfo_t *siginfop, timespec_t *timeoutp)
siginfofree(lwp->lwp_curinfo);
lwp->lwp_curinfo = NULL;
}
+ sigemptyset(&t->t_sigwait);
return (ret);
}