summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/os/sig.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/os/sig.c')
-rw-r--r--usr/src/uts/common/os/sig.c27
1 files changed, 16 insertions, 11 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;