diff options
Diffstat (limited to 'sysdeps/unix/sysv/linux/sigaction.c')
-rw-r--r-- | sysdeps/unix/sysv/linux/sigaction.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/sysdeps/unix/sysv/linux/sigaction.c b/sysdeps/unix/sysv/linux/sigaction.c index a7b3e07dae..161f1b0529 100644 --- a/sysdeps/unix/sysv/linux/sigaction.c +++ b/sysdeps/unix/sysv/linux/sigaction.c @@ -25,6 +25,13 @@ extern int __syscall_sigaction (int, const struct kernel_sigaction *, struct kernel_sigaction *); +extern int __syscall_rt_signal (int, const struct sigaction *, + struct sigaction *, size_t); + +/* The variable is shared between all wrappers around signal handling + functions which have RT equivalents. It is defined in sigsuspend.c. */ +extern int __libc_have_rt_sigs; + /* If ACT is not NULL, change the action for SIG to *ACT. If OACT is not NULL, put the old action for SIG in *OACT. */ @@ -34,12 +41,26 @@ __sigaction (sig, act, oact) const struct sigaction *act; struct sigaction *oact; { - struct kernel_sigaction k_sigact, k_osigact; + struct old_kernel_sigaction k_sigact, k_osigact; int error; + /* First try the RT signals. */ + if (__libc_have_rt_sigs) + { + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + int result = __syscall_rt_sigaction (sig, act, oact, + _NSIG / (8 * sizeof (long int))); + + if (result >= 0 || errno != ENOSYS) + return result; + + __libc_have_rt_sigs = 0; + } + if (act) { - k_sigact.sa_handler = act->sa_handler; + k_sigact.k_sa_handler = act->sa_handler; k_sigact.sa_mask = act->sa_mask.__val[0]; k_sigact.sa_flags = act->sa_flags; #ifdef HAVE_SA_RESTORER @@ -50,7 +71,7 @@ __sigaction (sig, act, oact) oact ? &k_osigact : 0); if (oact && error >= 0) { - oact->sa_handler = k_osigact.sa_handler; + oact->sa_handler = k_osigact.k_sa_handler; oact->sa_mask.__val[0] = k_osigact.sa_mask; oact->sa_flags = k_osigact.sa_flags; #ifdef HAVE_SA_RESTORER |