commit 055b96e76b6f7b8937828b89361f609a55a3df0f Author: Jeremie Koenig Date: Wed Jul 20 00:55:34 2011 +0000 fix sigwait for pending signals diff --git a/sysdeps/mach/hurd/sigwait.c b/sysdeps/mach/hurd/sigwait.c index af50f74..61316bc 100644 --- a/sysdeps/mach/hurd/sigwait.c +++ b/sysdeps/mach/hurd/sigwait.c @@ -11,41 +11,41 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include #include #include #include #include #include /* Select any of pending signals from SET or wait for any to arrive. */ int __sigwait (const sigset_t *set, int *sig) { struct hurd_sigstate *ss; - sigset_t mask, ready, blocked; + sigset_t mask, blocked; int signo = 0; struct hurd_signal_preemptor preemptor; jmp_buf buf; mach_port_t wait; mach_msg_header_t msg; sighandler_t preempt_fun (struct hurd_signal_preemptor *pe, struct hurd_sigstate *ss, int *sigp, struct hurd_signal_detail *detail) { if (signo) /* We've already been run; don't interfere. */ return SIG_ERR; signo = *sigp; /* Make sure this is all kosher */ assert (__sigismember (&mask, signo)); @@ -57,82 +57,74 @@ __sigwait (const sigset_t *set, int *sig) } void handler (int sig) { assert (sig == signo); longjmp (buf, 1); } wait = __mach_reply_port (); if (set != NULL) /* Crash before locking */ mask = *set; else __sigemptyset (&mask); ss = _hurd_self_sigstate (); _hurd_sigstate_lock (ss); - /* See if one of these signals is currently pending. */ - sigset_t pending = _hurd_sigstate_pending (ss); - __sigandset (&ready, &pending, &mask); - if (! __sigisemptyset (&ready)) - { - for (signo = 1; signo < NSIG; signo++) - if (__sigismember (&ready, signo)) - { - __sigdelset (&ready, signo); - goto all_done; - } - /* Huh? Where'd it go? */ - abort (); - } - - /* Wait for one of them to show up. */ + /* Wait for one of the signals in MASK to show up. */ if (!setjmp (buf)) { /* Make the preemptor */ preemptor.signals = mask; preemptor.first = 0; preemptor.last = -1; preemptor.preemptor = preempt_fun; preemptor.handler = handler; /* Install this preemptor */ preemptor.next = ss->preemptors; ss->preemptors = &preemptor; /* Unblock the expected signals */ blocked = ss->blocked; ss->blocked &= ~mask; + /* See if one of them is currently pending. */ + sigset_t ready = _hurd_sigstate_pending (ss); + __sigandset (&ready, &ready, &mask); + _hurd_sigstate_unlock (ss); + if (! __sigisemptyset (&ready)) + /* Send a message to the signal thread so it + will wake up and check for pending signals. */ + __msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ()); + /* Wait. */ __mach_msg (&msg, MACH_RCV_MSG, 0, sizeof (msg), wait, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); abort (); } else { assert (signo); _hurd_sigstate_lock (ss); /* Delete our preemptor. */ assert (ss->preemptors == &preemptor); ss->preemptors = preemptor.next; } - -all_done: _hurd_sigstate_unlock (ss); __mach_port_destroy (__mach_task_self (), wait); *sig = signo; return 0; } weak_alias (__sigwait, sigwait)