]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/unix/sysv/linux/i386/sigaction.c
.
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / i386 / sigaction.c
CommitLineData
efc755b2 1/* POSIX.1 `sigaction' call for Linux/i386.
32c075e1 2 Copyright (C) 1991,1995-2000,2002-2004,2005 Free Software Foundation, Inc.
4cca6b86 3 This file is part of the GNU C Library.
efc755b2 4
4cca6b86 5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
efc755b2 9
4cca6b86
UD
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 13 Lesser General Public License for more details.
efc755b2 14
41bdb6e2
AJ
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
efc755b2
RM
19
20#include <sysdep.h>
21#include <errno.h>
22#include <stddef.h>
23#include <signal.h>
ef52edfc 24#include <string.h>
efc755b2 25
adcb550c
UD
26#include <sysdep.h>
27#include <sys/syscall.h>
8e4f5035 28#include <ldsodefs.h>
adcb550c 29
ea6710d3
UD
30#include <kernel-features.h>
31
4cca6b86
UD
32/* The difference here is that the sigaction structure used in the
33 kernel is not the same as we use in the libc. Therefore we must
34 translate it here. */
35#include <kernel_sigaction.h>
36
25ee8743
UD
37/* We do not globally define the SA_RESTORER flag so do it here. */
38#define SA_RESTORER 0x04000000
39
efc755b2 40
ea6710d3 41#if __ASSUME_REALTIME_SIGNALS == 0
cbdee279 42/* The variable is shared between all wrappers around signal handling
b9b49b44 43 functions which have RT equivalents. */
da2d1bc5 44int __libc_missing_rt_sigs;
ea6710d3 45#endif
cbdee279 46
40e15c4d
UD
47/* Using the hidden attribute here does not change the code but it
48 helps to avoid warnings. */
32c075e1
JJ
49#if defined HAVE_HIDDEN && defined HAVE_VISIBILITY_ATTRIBUTE \
50 && !defined HAVE_BROKEN_VISIBILITY_ATTRIBUTE
51# ifdef __NR_rt_sigaction
40e15c4d 52extern void restore_rt (void) asm ("__restore_rt") attribute_hidden;
32c075e1 53# endif
78fbd00f 54extern void restore (void) asm ("__restore") attribute_hidden;
32c075e1
JJ
55#else
56# ifdef __NR_rt_sigaction
57static void restore_rt (void) asm ("__restore_rt");
58# endif
59static void restore (void) asm ("__restore");
60#endif
e0082312 61
cbdee279 62
efc755b2
RM
63/* If ACT is not NULL, change the action for SIG to *ACT.
64 If OACT is not NULL, put the old action for SIG in *OACT. */
65int
c0f53cdd 66__libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
efc755b2 67{
ea6710d3 68#if __ASSUME_REALTIME_SIGNALS == 0
cbdee279 69 struct old_kernel_sigaction k_newact, k_oldact;
ea6710d3 70#endif
efc755b2
RM
71 int result;
72
655b26bb 73#ifdef __NR_rt_sigaction
ea6710d3 74
cbdee279 75 /* First try the RT signals. */
ea6710d3 76# if __ASSUME_REALTIME_SIGNALS == 0
da2d1bc5 77 if (!__libc_missing_rt_sigs)
ea6710d3 78# endif
cbdee279 79 {
14e9dd67 80 struct kernel_sigaction kact, koact;
ea6710d3 81# if __ASSUME_REALTIME_SIGNALS == 0
8fb3e007 82 int saved_errno = errno;
ea6710d3 83# endif
cbdee279 84
d71b808a
UD
85 if (act)
86 {
14e9dd67 87 kact.k_sa_handler = act->sa_handler;
8e4f5035 88 kact.sa_flags = act->sa_flags;
14e9dd67 89 memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t));
7cc1894c 90
afdca0f2 91 if (GLRO(dl_sysinfo_dso) == NULL)
8e4f5035
UD
92 {
93 kact.sa_flags |= SA_RESTORER;
cbdee279 94
8e4f5035
UD
95 kact.sa_restorer = ((act->sa_flags & SA_SIGINFO)
96 ? &restore_rt : &restore);
97 }
d71b808a 98 }
cbdee279
UD
99
100 /* XXX The size argument hopefully will have to be changed to the
101 real size of the user-level sigset_t. */
4bbb61e4
GM
102 result = INLINE_SYSCALL (rt_sigaction, 4,
103 sig, act ? __ptrvalue (&kact) : NULL,
104 oact ? __ptrvalue (&koact) : NULL, _NSIG / 8);
cbdee279 105
ea6710d3 106# if __ASSUME_REALTIME_SIGNALS == 0
cbdee279 107 if (result >= 0 || errno != ENOSYS)
ea6710d3 108# endif
14e9dd67
UD
109 {
110 if (oact && result >= 0)
111 {
112 oact->sa_handler = koact.k_sa_handler;
113 memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t));
114 oact->sa_flags = koact.sa_flags;
115 oact->sa_restorer = koact.sa_restorer;
116 }
117 return result;
118 }
cbdee279 119
ea6710d3 120# if __ASSUME_REALTIME_SIGNALS == 0
8fb3e007 121 __set_errno (saved_errno);
da2d1bc5 122 __libc_missing_rt_sigs = 1;
ea6710d3 123# endif
cbdee279 124 }
655b26bb 125#endif
cbdee279 126
ea6710d3 127#if __ASSUME_REALTIME_SIGNALS == 0
3e2ee727 128 if (act)
efc755b2 129 {
cbdee279 130 k_newact.k_sa_handler = act->sa_handler;
4cca6b86 131 k_newact.sa_mask = act->sa_mask.__val[0];
61bdd24f 132 k_newact.sa_flags = act->sa_flags | SA_RESTORER;
4cca6b86 133
e0082312 134 k_newact.sa_restorer = &restore;
efc755b2
RM
135 }
136
6aca81bb
UD
137 result = INLINE_SYSCALL (sigaction, 3, sig,
138 act ? __ptrvalue (&k_newact) : 0,
139 oact ? __ptrvalue (&k_oldact) : 0);
efc755b2
RM
140
141 if (result < 0)
6aca81bb 142 return -1;
4cca6b86
UD
143
144 if (oact)
145 {
cbdee279 146 oact->sa_handler = k_oldact.k_sa_handler;
4cca6b86
UD
147 oact->sa_mask.__val[0] = k_oldact.sa_mask;
148 oact->sa_flags = k_oldact.sa_flags;
149 oact->sa_restorer = k_oldact.sa_restorer;
150 }
151
efc755b2 152 return 0;
ea6710d3 153#endif
efc755b2 154}
5ec5c857 155libc_hidden_def (__libc_sigaction)
efc755b2 156
8b4f1598
UD
157#ifdef WRAPPER_INCLUDE
158# include WRAPPER_INCLUDE
159#endif
160
bf293afe 161#ifndef LIBC_SIGACTION
ab18b1e1 162weak_alias (__libc_sigaction, __sigaction)
37ba7d66 163libc_hidden_weak (__sigaction)
c0f53cdd 164weak_alias (__libc_sigaction, sigaction)
ace55c73 165#endif
e0082312 166
adcf0e4a
UD
167/* NOTE: Please think twice before making any changes to the bits of
168 code below. GDB needs some intimate knowledge about it to
169 recognize them as signal trampolines, and make backtraces through
170 signal handlers work right. Important are both the names
171 (__restore and __restore_rt) and the exact instruction sequence.
172 If you ever feel the need to make any changes, please notify the
173 appropriate GDB maintainer. */
174
8e4f5035
UD
175#define RESTORE(name, syscall) RESTORE2 (name, syscall)
176#define RESTORE2(name, syscall) \
e0082312
UD
177asm \
178 ( \
4dbb6417
UD
179 ".text\n" \
180 " .align 16\n" \
adcf0e4a 181 "__" #name ":\n" \
e0082312
UD
182 " movl $" #syscall ", %eax\n" \
183 " int $0x80" \
184 );
185
8e4f5035 186#ifdef __NR_rt_sigaction
e0082312
UD
187/* The return code for realtime-signals. */
188RESTORE (restore_rt, __NR_rt_sigreturn)
8e4f5035 189#endif
e0082312
UD
190
191/* For the boring old signals. */
8e4f5035
UD
192#undef RESTORE2
193#define RESTORE2(name, syscall) \
e0082312
UD
194asm \
195 ( \
4dbb6417
UD
196 ".text\n" \
197 " .align 8\n" \
adcf0e4a 198 "__" #name ":\n" \
e0082312
UD
199 " popl %eax\n" \
200 " movl $" #syscall ", %eax\n" \
201 " int $0x80" \
202 );
203
204RESTORE (restore, __NR_sigreturn)