diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2022-11-07 21:14:39 +0100 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2022-11-07 21:16:26 +0100 |
commit | 19934d629ee22bbd332f04da4320e4f624c9560c (patch) | |
tree | 630cf9f3329fbb34edcd26198d924a96f2cadfa2 /sysdeps | |
parent | 8d291eabd541029d7ac705cc1ea112c58dfbb05f (diff) | |
download | glibc-19934d629ee22bbd332f04da4320e4f624c9560c.tar.gz glibc-19934d629ee22bbd332f04da4320e4f624c9560c.tar.xz glibc-19934d629ee22bbd332f04da4320e4f624c9560c.zip |
hurd: Add sigtimedwait and sigwaitinfo support
This simply needed to add the timeout parameter to mach_msg, and copy information from struct hurd_signal_detail.
Diffstat (limited to 'sysdeps')
-rw-r--r-- | sysdeps/mach/hurd/sigtimedwait.c | 170 | ||||
-rw-r--r-- | sysdeps/mach/hurd/sigwait.c | 121 | ||||
-rw-r--r-- | sysdeps/mach/hurd/sigwaitinfo.c | 28 |
3 files changed, 207 insertions, 112 deletions
diff --git a/sysdeps/mach/hurd/sigtimedwait.c b/sysdeps/mach/hurd/sigtimedwait.c new file mode 100644 index 0000000000..cc5b383ea6 --- /dev/null +++ b/sysdeps/mach/hurd/sigtimedwait.c @@ -0,0 +1,170 @@ +/* Implementation of sigtimedwait function from POSIX.1b. + Copyright (C) 1996-2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + 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, see + <https://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <hurd.h> +#include <hurd/signal.h> +#include <hurd/msg.h> +#include <hurd/sigpreempt.h> +#include <assert.h> +#include <sysdep-cancel.h> + +int +__sigtimedwait (const sigset_t *set, siginfo_t *info, + const struct timespec *timeout) +{ + struct hurd_sigstate *ss; + sigset_t mask, ready, blocked; + int signo = 0; + struct hurd_signal_preemptor preemptor; + jmp_buf buf; + mach_port_t wait; + mach_msg_header_t msg; + int cancel_oldtype; + mach_msg_option_t option = 0; + mach_msg_timeout_t ms = MACH_MSG_TIMEOUT_NONE; + + 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; + + if (info) + { + info->si_signo = signo; + info->si_errno = detail->error; + info->si_code = detail->code; + + /* XXX */ + info->si_pid = -1; + info->si_uid = -1; + info->si_addr = (void *) NULL; + info->si_status = 0; + info->si_band = 0; + info->si_value.sival_int = 0; + } + + /* Make sure this is all kosher */ + assert (__sigismember (&mask, signo)); + + /* Restore the blocking mask. */ + ss->blocked = blocked; + + return pe->handler; + } + + 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 (); + cancel_oldtype = LIBC_CANCEL_ASYNC(); + _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. */ + + 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; + + _hurd_sigstate_unlock (ss); + + if (timeout) + { + option |= MACH_RCV_TIMEOUT, + ms = timeout->tv_sec * 1000 + + (timeout->tv_nsec + 999999) / 1000000; + } + + /* Wait. */ + __mach_msg (&msg, MACH_RCV_MSG | option, 0, sizeof (msg), wait, + ms, MACH_PORT_NULL); + + if (!(option & MACH_RCV_TIMEOUT)) + abort (); + + /* Timed out. */ + signo = __hurd_fail (EAGAIN); + } + else + { + assert (signo); + + _hurd_sigstate_lock (ss); + + /* Delete our preemptor. */ + assert (ss->preemptors == &preemptor); + ss->preemptors = preemptor.next; + } + + +all_done: + _hurd_sigstate_unlock (ss); + LIBC_CANCEL_RESET (cancel_oldtype); + + __mach_port_destroy (__mach_task_self (), wait); + return signo; +} +libc_hidden_def (__sigtimedwait) +weak_alias (__sigtimedwait, sigtimedwait) diff --git a/sysdeps/mach/hurd/sigwait.c b/sysdeps/mach/hurd/sigwait.c index 9d2dfe13ee..caf1aef933 100644 --- a/sysdeps/mach/hurd/sigwait.c +++ b/sysdeps/mach/hurd/sigwait.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-2022 Free Software Foundation, Inc. +/* Copyright (C) 2022 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -15,128 +15,25 @@ License along with the GNU C Library; if not, see <https://www.gnu.org/licenses/>. */ -#include <errno.h> +#include <signal.h> #include <hurd.h> -#include <hurd/signal.h> -#include <hurd/msg.h> -#include <hurd/sigpreempt.h> -#include <assert.h> -#include <sysdep-cancel.h> /* 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; - int signo = 0; - struct hurd_signal_preemptor preemptor; - jmp_buf buf; - mach_port_t wait; - mach_msg_header_t msg; - int cancel_oldtype; + int ret; - 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; + ret = __sigtimedwait (set, NULL, NULL); - signo = *sigp; + if (ret < 0) + return -1; - /* Make sure this is all kosher */ - assert (__sigismember (&mask, signo)); + if (!ret) + return __hurd_fail(EAGAIN); - /* Restore the blocking mask. */ - ss->blocked = blocked; - - return pe->handler; - } - - 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 (); - cancel_oldtype = LIBC_CANCEL_ASYNC(); - _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. */ - - 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; - - _hurd_sigstate_unlock (ss); - - /* 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); - LIBC_CANCEL_RESET (cancel_oldtype); - - __mach_port_destroy (__mach_task_self (), wait); - *sig = signo; + *sig = ret; return 0; } - libc_hidden_def (__sigwait) weak_alias (__sigwait, sigwait) diff --git a/sysdeps/mach/hurd/sigwaitinfo.c b/sysdeps/mach/hurd/sigwaitinfo.c new file mode 100644 index 0000000000..d70f62328c --- /dev/null +++ b/sysdeps/mach/hurd/sigwaitinfo.c @@ -0,0 +1,28 @@ +/* Implementation of sigwaitinfo function from POSIX.1b. + Copyright (C) 2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + 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, see + <https://www.gnu.org/licenses/>. */ + +#include <signal.h> +#include <stddef.h> + +int +__sigwaitinfo (const sigset_t *set, siginfo_t *info) +{ + return __sigtimedwait (set, info, NULL); +} +libc_hidden_def (__sigwaitinfo) +weak_alias (__sigwaitinfo, sigwaitinfo) |