blob: 667eeba4156889acd13180d5466a40e505a378c1 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001 All what you never wanted to know about sigaction(),
2 struct sigaction, and sigset_t.
3
4
5Before vda started messing with sigset_t, struct sigaction
6and sigaction() functions, things looked this way:
7
8
9 Structures
10
11MIPS:
12
13Ignoring bogus "#if defined(__mips__) ..." block in
14libc/sysdeps/linux/common/bits/kernel_sigaction.h
15and using
16libc/sysdeps/linux/mips/bits/kernel_sigaction.h
17as an authoritative source:
18
19HAVE_SA_RESTORER is #defined
20struct old_kernel_sigaction {
21 unsigned sa_flags;
22 sighandler_t k_sa_handler;
23 unsigned long sa_mask;
24 unsigned pad0[3]; /* reserved, keep size constant */
25 /* Abi says here follows reserved int[2] */
26 void (*sa_restorer)(void);
27#if (_MIPS_SZPTR < 64)
28 /* For 32 bit code we have to pad struct sigaction to get
29 * constant size for the ABI */
30 int pad1[1]; /* reserved */
31#endif
32};
33struct kernel_sigaction {
34 unsigned int sa_flags;
35 sighandler_t k_sa_handler;
36 kernel_sigset_t sa_mask;
37 void (*sa_restorer)(void);
38 int s_resv[1]; /* reserved */
39};
40struct sigaction {
41 unsigned sa_flags;
42 sighandler_t sa_handler;
43 sigset_t sa_mask;
44 /* The ABI says here are two unused ints following. */
45 /* Restore handler. */
46 void (*sa_restorer)(void);
47#if _MIPS_SZPTR < 64
48 int sa_resv[1];
49#endif
50};
51
52IA64:
53
54Has no old_sigaction. What a relief.
55
56struct kernel_sigaction {
57 sighandler_t k_sa_handler;
58 unsigned long sa_flags;
59 sigset_t sa_mask;
60};
61struct sigaction {
62 sighandler_t sa_handler;
63 unsigned long sa_flags;
64 sigset_t sa_mask;
65};
66
67Alpha:
68
69struct old_kernel_sigaction {
70 sighandler_t k_sa_handler;
71 unsigned long sa_mask;
72 unsigned sa_flags;
73};
74struct kernel_sigaction {
75 sighandler_t k_sa_handler;
76 unsigned sa_flags;
77 sigset_t sa_mask;
78};
79struct sigaction {
80 sighandler_t sa_handler;
81 sigset_t sa_mask;
82 unsigned sa_flags;
83};
84
85HPPA:
86
87struct kernel_sigaction {
88 sighandler_t k_sa_handler;
89 unsigned long sa_flags;
90 sigset_t sa_mask;
91};
92struct sigaction {
93 sighandler_t sa_handler;
94 unsigned long sa_flags;
95 sigset_t sa_mask;
96};
97
98The rest, kernel side:
99
100HAVE_SA_RESTORER #defined
101struct old_kernel_sigaction {
102 sighandler_t k_sa_handler;
103 unsigned long sa_mask;
104 unsigned long sa_flags;
105 void (*sa_restorer)(void);
106};
107struct kernel_sigaction {
108 sighandler_t k_sa_handler;
109 unsigned long sa_flags;
110 void (*sa_restorer)(void);
111 sigset_t sa_mask;
112};
113
114On userspace side, Sparc has special struct sigaction:
115
116struct sigaction {
117 sighandler_t sa_handler;
118 sigset_t sa_mask;
119 unsigned long sa_flags;
120 void (*sa_restorer)(void); /* Not used by Linux/Sparc */
121};
122
123And finally the rest has:
124
125struct sigaction {
126 sighandler_t sa_handler;
127 sigset_t sa_mask;
128 int sa_flags;
129 void (*sa_restorer)(void);
130};
131
132Userspace sigset_t was uniformly defined as vector of longs
133big enough to hold 1024 (!) bits - carried over from glibc.
134Since the only arch whose struct kernel_sigaction contains sa_mask
135not as a last member is MIPS, MIPS has special kernel_sigset_t,
136which is an array of longs long enough for 128 bits.
137Other arches still used userspace sigset_t in struct kernel_sigaction,
138but it did not really matter because overlong kernel_sigaction
139does not hurt in sigaction() [explained below].
140On kernel side, all arches define _NSIG to 65 (meaning
141there are 64 signals, 1..64) except MIPS, which define it to 129.
142
143
144 Functions
145
146sigaction() [libc function] usually has two kernel_sigaction's
147on stack and copy (userspace) struct sigaction members into
148first one, executes syscall, then pulls out the result from
149second one. This accomodates differences in layouts of structs.
150
151The only typically present quirk is what to do with sa_restorer.
152
153 libc/sysdeps/linux/arm/sigaction.c
154
155if HAVE_SA_RESTORER and (sa_flags & SA_RESTORER) is not set,
156sets sa_restorer to
157(flags & SA_SIGINFO) ? __default_rt_sa_restorer : __default_sa_restorer,
158and sets SA_RESTORER,
159otherwise passes it as-is. Which is kinda strange, because AFAICS
160HAVE_SA_RESTORER is *not* defined for ARM.
161
162 libc/sysdeps/linux/i386/sigaction.c
163
164Forcibly sets SA_RESTORER and sa_restorer:
165kact.sa_flags = act->sa_flags | SA_RESTORER;
166kact.sa_restorer = ((act->sa_flags & SA_SIGINFO) ? &restore_rt : &restore);
167
168 libc/sysdeps/linux/x86_64/sigaction.c
169
170Forcibly sets SA_RESTORER and sa_restorer:
171kact.sa_flags = act->sa_flags | SA_RESTORER;
172kact.sa_restorer = &restore_rt;
173
174 libc/sysdeps/linux/mips/sigaction.c
175
176# ifdef HAVE_SA_RESTORER
177# if _MIPS_SIM == _ABIO32
178 kact.sa_restorer = act->sa_restorer;
179# else
180 kact.sa_restorer = &restore_rt;
181# endif
182# endif
183No confusion here, HAVE_SA_RESTORER is #defined for MIPS
184
185 libc/sysdeps/linux/avr32/sigaction.c
186
187if (kact.sa_flags & SA_RESTORER) {
188 kact.sa_restorer = act->sa_restorer;
189} else {
190 kact.sa_restorer = __default_rt_sa_restorer;
191 kact.sa_flags |= SA_RESTORER;
192}
193Does not check HAVE_SA_RESTORER, but avr32 falls
194in "completely ordinary" category on both kernel and
195userspace sides, and those have it defined.
196
197 libc/sysdeps/linux/xtensa/sigaction.c
198
199if (kact.sa_flags & SA_RESTORER) {
200 kact.sa_restorer = act->sa_restorer;
201} else {
202 kact.sa_restorer = __default_sa_restorer;
203 kact.sa_flags |= SA_RESTORER;
204}
205Thus, similar to avr32.
206
207 libc/signal/sigaction.c (i.e. the all other arches)
208
209# ifdef HAVE_SA_RESTORER
210 kact.sa_restorer = act->sa_restorer;
211# endif
212Plain translation, just sa_restorer copy is protected
213by HAVE_SA_RESTORER #define check. Looks like here
214HAVE_SA_RESTORER will be undef'ed only for IA64,
215Alpha an HPPA.
216
217
218 Proposed overhaul past 0.9.30
219
220Since we can define libc-side structures at will:
221make sigset_t and struct sigaction identical on kernel side and libc side
222within each arch. If arches do not need special handling of sa_restorer,
223then sigaction() can directly use passed struct sigaction as-is.
224Otherwise, a copy is still needed, although sigaction() might have
225just one struct kernel_sigaction on stack and use it both for passing
226data to kernel and for receiving it back. Might save a few bytes.
227
228To this effect:
229
230* Make sigset_t size match kernel side on all arches.
231 This is easy since all arches have 64 signals and only MIPS has 128.
232
233* Modify libc/sysdeps/linux/$ARCH/bits/sigaction.h
234 so that its struct sigaction matches kernel's. If sa_restorer
235 field is present in libc but is missing in kernel_sigaction,
236 add it at the bottom in order to not mess up kernel_sigaction layout.
237
238* Modify libc/sysdeps/linux/$ARCH/sigaction.c
239 to implement the logic above. In "common" pseudo-arch
240 (libc/signal/sigaction.c file),
241 we would not even need to do any copying, as described above.
242
243* Document discovered arch quirks while debugging this mess.
244
245* struct old_kernel_sigaction can't be disposed of in a similar way,
246 we need to have userspace struct sigaction unchanged regardless
247 whether we use "old" or "new" kernel sigaction() syscall.
248 It's moot anyway because "old" one is long unused, it's from
249 pre-2.2 kernels.