diff options
author | Roger A. Faulkner <Roger.Faulkner@Sun.COM> | 2009-04-16 15:36:18 -0700 |
---|---|---|
committer | Roger A. Faulkner <Roger.Faulkner@Sun.COM> | 2009-04-16 15:36:18 -0700 |
commit | 9524a69f24734e80c50bfc33c4f1bce173d465a1 (patch) | |
tree | d9d772eca43402eff175e4aa1c2efc76b629e868 | |
parent | 6075fa3de0c83fd23d9e870137abc5f442e9eee2 (diff) | |
download | illumos-gate-9524a69f24734e80c50bfc33c4f1bce173d465a1.tar.gz |
6565817 sigwait can't wait for SIGTSTP
-rw-r--r-- | usr/src/uts/common/os/sig.c | 27 | ||||
-rw-r--r-- | usr/src/uts/common/sys/thread.h | 1 | ||||
-rw-r--r-- | usr/src/uts/common/syscall/sigtimedwait.c | 23 |
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); } |