blob: d5e5f4fd399a736ebf820e2c907c5d50e7ebf338 [file] [log] [blame]
njnde62cbf2005-06-10 22:08:14 +00001
2/*--------------------------------------------------------------------*/
3/*--- Signal-related libc stuff. m_libcsignal.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
Elliott Hughesed398002017-06-21 14:41:24 -070010 Copyright (C) 2000-2017 Julian Seward
njnde62cbf2005-06-10 22:08:14 +000011 jseward@acm.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
sewardj1383bdd2006-10-17 01:30:47 +000032#include "pub_core_debuglog.h"
sewardj4cfea4f2006-10-14 19:26:10 +000033#include "pub_core_vki.h"
sewardj1383bdd2006-10-17 01:30:47 +000034#include "pub_core_vkiscnums.h"
njnde62cbf2005-06-10 22:08:14 +000035#include "pub_core_libcbase.h"
36#include "pub_core_libcassert.h"
njn9abd6082005-06-17 21:31:45 +000037#include "pub_core_syscall.h"
sewardj1383bdd2006-10-17 01:30:47 +000038#include "pub_core_libcsignal.h" /* self */
njnde62cbf2005-06-10 22:08:14 +000039
sewardj8eb8bab2015-07-21 14:44:28 +000040#if !defined(VGO_solaris)
41# define _VKI_MAXSIG (_VKI_NSIG - 1)
42#endif
43STATIC_ASSERT((_VKI_MAXSIG % _VKI_NSIG_BPW) != 0);
44
njnf76d27a2009-05-28 01:53:07 +000045/* IMPORTANT: on Darwin it is essential to use the _nocancel versions
46 of syscalls rather than the vanilla version, if a _nocancel version
47 is available. See docs/internals/Darwin-notes.txt for the reason
48 why. */
49
njnde62cbf2005-06-10 22:08:14 +000050/* sigemptyset, sigfullset, sigaddset and sigdelset return 0 on
51 success and -1 on error. */
njncda2f0f2009-05-18 02:12:08 +000052/* In the sigset routines below, be aware that _VKI_NSIG_BPW can be
53 either 32 or 64, and hence the sig[] words can either be 32- or
54 64-bits. And which they are it doesn't necessarily follow from the
55 host word size. */
njnde62cbf2005-06-10 22:08:14 +000056
sewardj8eb8bab2015-07-21 14:44:28 +000057/* Functions VG_(isemptysigset) and VG_(isfullsigset) check only bits that
58 represent valid signals (i.e. signals <= _VKI_MAXSIG). The same applies
59 for the comparison in VG_(iseqsigset). This is important because when
60 a signal set is received from an operating system then bits which represent
61 signals > _VKI_MAXSIG can have unexpected values for Valgrind. This is
62 mainly specific to the Solaris kernel which clears these bits. */
63
njnde62cbf2005-06-10 22:08:14 +000064Int VG_(sigfillset)( vki_sigset_t* set )
65{
66 Int i;
67 if (set == NULL)
68 return -1;
69 for (i = 0; i < _VKI_NSIG_WORDS; i++)
njncda2f0f2009-05-18 02:12:08 +000070 set->sig[i] = ~0;
njnde62cbf2005-06-10 22:08:14 +000071 return 0;
72}
73
74Int VG_(sigemptyset)( vki_sigset_t* set )
75{
76 Int i;
77 if (set == NULL)
78 return -1;
79 for (i = 0; i < _VKI_NSIG_WORDS; i++)
njncda2f0f2009-05-18 02:12:08 +000080 set->sig[i] = 0;
njnde62cbf2005-06-10 22:08:14 +000081 return 0;
82}
83
84Bool VG_(isemptysigset)( const vki_sigset_t* set )
85{
86 Int i;
87 vg_assert(set != NULL);
sewardj8eb8bab2015-07-21 14:44:28 +000088 for (i = 0; i < _VKI_NSIG_WORDS; i++) {
89 if (_VKI_NSIG_BPW * (i + 1) <= (_VKI_MAXSIG + 1)) {
90 /* Full word check. */
91 if (set->sig[i] != 0) return False;
92 }
93 else {
94 /* Partial word check. */
95 ULong mask = (1UL << (_VKI_MAXSIG % _VKI_NSIG_BPW)) - 1;
96 if ((set->sig[i] & mask) != 0) return False;
97 break;
98 }
99 }
njnde62cbf2005-06-10 22:08:14 +0000100 return True;
101}
102
103Bool VG_(isfullsigset)( const vki_sigset_t* set )
104{
105 Int i;
106 vg_assert(set != NULL);
sewardj8eb8bab2015-07-21 14:44:28 +0000107 for (i = 0; i < _VKI_NSIG_WORDS; i++) {
108 if (_VKI_NSIG_BPW * (i + 1) <= (_VKI_MAXSIG + 1)) {
109 /* Full word check. */
110 if (set->sig[i] != ~0) return False;
111 }
112 else {
113 /* Partial word check. */
114 ULong mask = (1UL << (_VKI_MAXSIG % _VKI_NSIG_BPW)) - 1;
115 if ((set->sig[i] & mask) != mask) return False;
116 break;
117 }
118 }
njnde62cbf2005-06-10 22:08:14 +0000119 return True;
120}
121
122Bool VG_(iseqsigset)( const vki_sigset_t* set1, const vki_sigset_t* set2 )
123{
124 Int i;
125 vg_assert(set1 != NULL && set2 != NULL);
sewardj8eb8bab2015-07-21 14:44:28 +0000126 for (i = 0; i < _VKI_NSIG_WORDS; i++) {
127 if (_VKI_NSIG_BPW * (i + 1) <= (_VKI_MAXSIG + 1)) {
128 /* Full word comparison. */
129 if (set1->sig[i] != set2->sig[i]) return False;
130 }
131 else {
132 /* Partial word comparison. */
133 ULong mask = (1UL << (_VKI_MAXSIG % _VKI_NSIG_BPW)) - 1;
florian212b5002015-08-19 10:09:08 +0000134 if ((set1->sig[i] & mask) != (set2->sig[i] & mask)) return False;
sewardj8eb8bab2015-07-21 14:44:28 +0000135 break;
136 }
137 }
njnde62cbf2005-06-10 22:08:14 +0000138 return True;
139}
140
141
142Int VG_(sigaddset)( vki_sigset_t* set, Int signum )
143{
144 if (set == NULL)
145 return -1;
146 if (signum < 1 || signum > _VKI_NSIG)
147 return -1;
148 signum--;
njncda2f0f2009-05-18 02:12:08 +0000149 set->sig[signum / _VKI_NSIG_BPW] |= (1ULL << (signum % _VKI_NSIG_BPW));
njnde62cbf2005-06-10 22:08:14 +0000150 return 0;
151}
152
153Int VG_(sigdelset)( vki_sigset_t* set, Int signum )
154{
155 if (set == NULL)
156 return -1;
157 if (signum < 1 || signum > _VKI_NSIG)
158 return -1;
159 signum--;
njncda2f0f2009-05-18 02:12:08 +0000160 set->sig[signum / _VKI_NSIG_BPW] &= ~(1ULL << (signum % _VKI_NSIG_BPW));
njnde62cbf2005-06-10 22:08:14 +0000161 return 0;
162}
163
164Int VG_(sigismember) ( const vki_sigset_t* set, Int signum )
165{
166 if (set == NULL)
167 return 0;
168 if (signum < 1 || signum > _VKI_NSIG)
169 return 0;
170 signum--;
171 if (1 & ((set->sig[signum / _VKI_NSIG_BPW]) >> (signum % _VKI_NSIG_BPW)))
172 return 1;
173 else
174 return 0;
175}
176
njnde62cbf2005-06-10 22:08:14 +0000177/* Add all signals in src to dst. */
florian32971242014-10-23 17:47:15 +0000178void VG_(sigaddset_from_set)( vki_sigset_t* dst, const vki_sigset_t* src )
njnde62cbf2005-06-10 22:08:14 +0000179{
180 Int i;
181 vg_assert(dst != NULL && src != NULL);
182 for (i = 0; i < _VKI_NSIG_WORDS; i++)
183 dst->sig[i] |= src->sig[i];
184}
185
186/* Remove all signals in src from dst. */
florian32971242014-10-23 17:47:15 +0000187void VG_(sigdelset_from_set)( vki_sigset_t* dst, const vki_sigset_t* src )
njnde62cbf2005-06-10 22:08:14 +0000188{
189 Int i;
190 vg_assert(dst != NULL && src != NULL);
191 for (i = 0; i < _VKI_NSIG_WORDS; i++)
192 dst->sig[i] &= ~(src->sig[i]);
193}
194
njncda2f0f2009-05-18 02:12:08 +0000195/* dst = dst `intersect` src. */
florian32971242014-10-23 17:47:15 +0000196void VG_(sigintersectset)( vki_sigset_t* dst, const vki_sigset_t* src )
njncda2f0f2009-05-18 02:12:08 +0000197{
198 Int i;
199 vg_assert(dst != NULL && src != NULL);
200 for (i = 0; i < _VKI_NSIG_WORDS; i++)
201 dst->sig[i] &= src->sig[i];
202}
203
204/* dst = ~src */
florian32971242014-10-23 17:47:15 +0000205void VG_(sigcomplementset)( vki_sigset_t* dst, const vki_sigset_t* src )
njncda2f0f2009-05-18 02:12:08 +0000206{
207 Int i;
208 vg_assert(dst != NULL && src != NULL);
209 for (i = 0; i < _VKI_NSIG_WORDS; i++)
210 dst->sig[i] = ~ src->sig[i];
211}
212
njnde62cbf2005-06-10 22:08:14 +0000213
214/* The functions sigaction, sigprocmask, sigpending and sigsuspend
215 return 0 on success and -1 on error.
216*/
217Int VG_(sigprocmask)( Int how, const vki_sigset_t* set, vki_sigset_t* oldset)
218{
sewardj8eb8bab2015-07-21 14:44:28 +0000219# if defined(VGO_linux) || defined(VGO_solaris)
njncda2f0f2009-05-18 02:12:08 +0000220# if defined(__NR_rt_sigprocmask)
njnde62cbf2005-06-10 22:08:14 +0000221 SysRes res = VG_(do_syscall4)(__NR_rt_sigprocmask,
222 how, (UWord)set, (UWord)oldset,
223 _VKI_NSIG_WORDS * sizeof(UWord));
njncda2f0f2009-05-18 02:12:08 +0000224# else
225 SysRes res = VG_(do_syscall3)(__NR_sigprocmask,
226 how, (UWord)set, (UWord)oldset);
227# endif
228
njnf76d27a2009-05-28 01:53:07 +0000229# elif defined(VGO_darwin)
230 /* On Darwin, __NR_sigprocmask appears to affect the entire
231 process, not just this thread. Hence need to use
232 __NR___pthread_sigmask instead. */
233 SysRes res = VG_(do_syscall3)(__NR___pthread_sigmask,
234 how, (UWord)set, (UWord)oldset);
njncda2f0f2009-05-18 02:12:08 +0000235# else
236# error "Unknown OS"
237# endif
238 return sr_isError(res) ? -1 : 0;
njnde62cbf2005-06-10 22:08:14 +0000239}
240
241
njnf76d27a2009-05-28 01:53:07 +0000242#if defined(VGO_darwin)
243/* A helper function for sigaction on Darwin. */
244static
245void darwin_signal_demux(void* a1, UWord a2, UWord a3, void* a4, void* a5) {
246 VG_(debugLog)(2, "libcsignal",
247 "PRE demux sig, a2 = %lu, signo = %lu\n", a2, a3);
248 if (a2 == 1)
249 ((void(*)(int))a1) (a3);
250 else
251 ((void(*)(int,void*,void*))a1) (a3,a4,a5);
252 VG_(debugLog)(2, "libcsignal",
253 "POST demux sig, a2 = %lu, signo = %lu\n", a2, a3);
254 VG_(do_syscall2)(__NR_sigreturn, (UWord)a5, 0x1E);
255 /* NOTREACHED */
256 __asm__ __volatile__("ud2");
257}
258#endif
259
njncda2f0f2009-05-18 02:12:08 +0000260Int VG_(sigaction) ( Int signum,
261 const vki_sigaction_toK_t* act,
262 vki_sigaction_fromK_t* oldact)
njnde62cbf2005-06-10 22:08:14 +0000263{
sewardj6e9de462011-06-28 07:25:29 +0000264# if defined(VGO_linux)
njncda2f0f2009-05-18 02:12:08 +0000265 /* Normal case: vki_sigaction_toK_t and vki_sigaction_fromK_t are
266 identical types. */
njnde62cbf2005-06-10 22:08:14 +0000267 SysRes res = VG_(do_syscall4)(__NR_rt_sigaction,
268 signum, (UWord)act, (UWord)oldact,
269 _VKI_NSIG_WORDS * sizeof(UWord));
njncda2f0f2009-05-18 02:12:08 +0000270 return sr_isError(res) ? -1 : 0;
271
njnf76d27a2009-05-28 01:53:07 +0000272# elif defined(VGO_darwin)
273 /* If we're passing a new action to the kernel, make a copy of the
274 new action, install our own sa_tramp field in it, and ignore
275 whatever we were provided with. This is OK because all the
276 sigaction requests come from m_signals, and are not directly
277 what the client program requested, so there is no chance that we
Elliott Hughesed398002017-06-21 14:41:24 -0700278 will inadvertently ignore the sa_tramp field requested by the
njnf76d27a2009-05-28 01:53:07 +0000279 client. (In fact m_signals does ignore it when building signal
280 frames for the client, but that's a completely different
281 matter).
282
283 If we're receiving an old action from the kernel, be very
284 paranoid and make sure the kernel doesn't trash bits of memory
285 that we don't expect it to. */
286 SysRes res;
287
288 vki_sigaction_toK_t actCopy;
289 struct {
290 ULong before[2];
291 vki_sigaction_fromK_t oa;
292 ULong after[2];
293 }
294 oldactCopy;
295
296 vki_sigaction_toK_t* real_act;
297 vki_sigaction_fromK_t* real_oldact;
298
299 real_act = act ? &actCopy : NULL;
300 real_oldact = oldact ? &oldactCopy.oa : NULL;
301 VG_(memset)(&oldactCopy, 0x55, sizeof(oldactCopy));
302 if (real_act) {
303 *real_act = *act;
304 real_act->sa_tramp = (void*)&darwin_signal_demux;
305 }
306 res = VG_(do_syscall3)(__NR_sigaction,
307 signum, (UWord)real_act, (UWord)real_oldact);
308 if (real_oldact) {
309 vg_assert(oldactCopy.before[0] == 0x5555555555555555ULL);
310 vg_assert(oldactCopy.before[1] == 0x5555555555555555ULL);
311 vg_assert(oldactCopy.after[0] == 0x5555555555555555ULL);
312 vg_assert(oldactCopy.after[1] == 0x5555555555555555ULL);
313 *oldact = *real_oldact;
314 }
315 return sr_isError(res) ? -1 : 0;
316
sewardj8eb8bab2015-07-21 14:44:28 +0000317# elif defined(VGO_solaris)
318 /* vki_sigaction_toK_t and vki_sigaction_fromK_t are identical types. */
319 SysRes res = VG_(do_syscall3)(__NR_sigaction,
320 signum, (UWord)act, (UWord)oldact);
321 return sr_isError(res) ? -1 : 0;
322
njncda2f0f2009-05-18 02:12:08 +0000323# else
324# error "Unsupported OS"
325# endif
326}
327
328
329/* See explanation in pub_core_libcsignal.h. */
330void
florian32971242014-10-23 17:47:15 +0000331VG_(convert_sigaction_fromK_to_toK)( const vki_sigaction_fromK_t* fromK,
njncda2f0f2009-05-18 02:12:08 +0000332 /*OUT*/vki_sigaction_toK_t* toK )
333{
sewardj8eb8bab2015-07-21 14:44:28 +0000334# if defined(VGO_linux) || defined(VGO_solaris)
njncda2f0f2009-05-18 02:12:08 +0000335 *toK = *fromK;
njnf76d27a2009-05-28 01:53:07 +0000336# elif defined(VGO_darwin)
337 toK->ksa_handler = fromK->ksa_handler;
338 toK->sa_tramp = NULL; /* the cause of all the difficulty */
339 toK->sa_mask = fromK->sa_mask;
340 toK->sa_flags = fromK->sa_flags;
njncda2f0f2009-05-18 02:12:08 +0000341# else
342# error "Unsupported OS"
343# endif
njnde62cbf2005-06-10 22:08:14 +0000344}
345
346
njnde62cbf2005-06-10 22:08:14 +0000347Int VG_(kill)( Int pid, Int signo )
348{
sewardj8eb8bab2015-07-21 14:44:28 +0000349# if defined(VGO_linux) || defined(VGO_solaris)
njnde62cbf2005-06-10 22:08:14 +0000350 SysRes res = VG_(do_syscall2)(__NR_kill, pid, signo);
njnf76d27a2009-05-28 01:53:07 +0000351# elif defined(VGO_darwin)
352 SysRes res = VG_(do_syscall3)(__NR_kill,
353 pid, signo, 1/*posix-compliant*/);
354# else
355# error "Unsupported OS"
356# endif
njncda2f0f2009-05-18 02:12:08 +0000357 return sr_isError(res) ? -1 : 0;
njnde62cbf2005-06-10 22:08:14 +0000358}
359
njn99109fe2009-05-20 07:10:48 +0000360Int VG_(tkill)( Int lwpid, Int signo )
njnde62cbf2005-06-10 22:08:14 +0000361{
njncda2f0f2009-05-18 02:12:08 +0000362# if defined(__NR_tkill)
njnde62cbf2005-06-10 22:08:14 +0000363 SysRes res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
njn99109fe2009-05-20 07:10:48 +0000364 res = VG_(do_syscall2)(__NR_tkill, lwpid, signo);
njncda2f0f2009-05-18 02:12:08 +0000365 if (sr_isError(res) && sr_Err(res) == VKI_ENOSYS)
njn99109fe2009-05-20 07:10:48 +0000366 res = VG_(do_syscall2)(__NR_kill, lwpid, signo);
njncda2f0f2009-05-18 02:12:08 +0000367 return sr_isError(res) ? -1 : 0;
368
njnf76d27a2009-05-28 01:53:07 +0000369# elif defined(VGO_darwin)
370 // Note that the __pthread_kill syscall takes a Mach thread, not a pthread.
371 SysRes res;
372 res = VG_(do_syscall2)(__NR___pthread_kill, lwpid, signo);
373 return sr_isError(res) ? -1 : 0;
374
sewardj8eb8bab2015-07-21 14:44:28 +0000375# elif defined(VGO_solaris)
376 SysRes res;
377# if defined(SOLARIS_LWP_SIGQUEUE_SYSCALL)
378# if defined(SOLARIS_LWP_SIGQUEUE_SYSCALL_TAKES_PID)
379 res = VG_(do_syscall6)(__NR_lwp_sigqueue, 0, lwpid, signo,
380 0, VKI_SI_LWP, 0);
381# else
382 res = VG_(do_syscall5)(__NR_lwp_sigqueue, lwpid, signo,
383 0, VKI_SI_LWP, 0);
384# endif
385# else
386 res = VG_(do_syscall2)(__NR_lwp_kill, lwpid, signo);
387# endif
388 return sr_isError(res) ? -1 : 0;
389
njncda2f0f2009-05-18 02:12:08 +0000390# else
391# error "Unsupported plat"
392# endif
njnde62cbf2005-06-10 22:08:14 +0000393}
394
njncda2f0f2009-05-18 02:12:08 +0000395/* ---------------------- sigtimedwait_zero ----------------------- */
sewardj1383bdd2006-10-17 01:30:47 +0000396
397/* A cut-down version of POSIX sigtimedwait: poll for pending signals
398 mentioned in the sigset_t, and if any are present, select one
399 arbitrarily, return its number (which must be > 0), and put
400 auxiliary info about it in the siginfo_t, and make it
401 not-pending-any-more. If none are pending, return zero. The _zero
402 refers to the fact that there is zero timeout, so if no signals are
403 pending it returns immediately. Perhaps a better name would be
404 'sigpoll'. Returns -1 on error, 0 if no signals pending, and n > 0
405 if signal n was selected.
406
407 The Linux implementation is trivial: do the corresponding syscall.
408
sewardj6e9de462011-06-28 07:25:29 +0000409 The Darwin implementation is horrible and probably broken in a dozen
sewardj1383bdd2006-10-17 01:30:47 +0000410 obscure ways. I suspect it's only thread-safe because V forces
411 single-threadedness. */
412
njncda2f0f2009-05-18 02:12:08 +0000413/* ---------- sigtimedwait_zero: Linux ----------- */
414
sewardj1383bdd2006-10-17 01:30:47 +0000415#if defined(VGO_linux)
416Int VG_(sigtimedwait_zero)( const vki_sigset_t *set,
417 vki_siginfo_t *info )
418{
419 static const struct vki_timespec zero = { 0, 0 };
420 SysRes res = VG_(do_syscall4)(__NR_rt_sigtimedwait, (UWord)set, (UWord)info,
421 (UWord)&zero, sizeof(*set));
njncda2f0f2009-05-18 02:12:08 +0000422 return sr_isError(res) ? -1 : sr_Res(res);
sewardj1383bdd2006-10-17 01:30:47 +0000423}
424
njnf76d27a2009-05-28 01:53:07 +0000425/* ---------- sigtimedwait_zero: Darwin ----------- */
426
427#elif defined(VGO_darwin)
428
429//static void show_set ( HChar* str, const vki_sigset_t* set ) {
430// Int i;
431// VG_(printf)("%s { ", str);
432// for (i = 1; i <= _VKI_NSIG; i++) {
433// if (VG_(sigismember)(set, i))
434// VG_(printf)("%u ", i);
435// }
436// VG_(printf)("}\n");
437//}
438
sewardj6e9de462011-06-28 07:25:29 +0000439/* The general idea is:
440 - use sigpending to find out which signals are pending
441 - choose one
442 - temporarily set its handler to sigtimedwait_zero_handler
443 - use sigsuspend atomically unblock it and wait for the signal.
444 Upon return, sigsuspend restores the signal mask to what it
445 was to start with.
446 - Restore the handler for the signal to whatever it was before.
447*/
448
449/* A signal handler which does nothing (it doesn't need to). It does
450 however check that it's not handing a sync signal for which
451 returning is meaningless. */
njnf76d27a2009-05-28 01:53:07 +0000452static void sigtimedwait_zero_handler ( Int sig )
453{
454 /* XXX this is wrong -- get rid of these. We could
455 get _any_ signal here */
456 vg_assert(sig != VKI_SIGILL);
457 vg_assert(sig != VKI_SIGSEGV);
458 vg_assert(sig != VKI_SIGBUS);
459 vg_assert(sig != VKI_SIGTRAP);
460 /* do nothing */
461}
462
463Int VG_(sigtimedwait_zero)( const vki_sigset_t *set,
464 vki_siginfo_t *info )
465{
466 const Bool debug = False;
467 Int i, ir;
468 SysRes sr;
469 vki_sigset_t pending, blocked, allbutone;
470 vki_sigaction_toK_t sa, saved_sa2;
471 vki_sigaction_fromK_t saved_sa;
472
473 //show_set("STWZ: looking for", set);
474
475 /* Find out what's pending: Darwin sigpending */
476 sr = VG_(do_syscall1)(__NR_sigpending, (UWord)&pending);
477 vg_assert(!sr_isError(sr));
478
479 /* don't try for signals not in 'set' */
480 /* pending = pending `intersect` set */
rhyskidd358f2842015-10-19 10:18:28 +0000481 VG_(sigintersectset)(&pending, (const vki_sigset_t*)set);
njnf76d27a2009-05-28 01:53:07 +0000482
483 /* don't try for signals not blocked at the moment */
484 ir = VG_(sigprocmask)(VKI_SIG_SETMASK, NULL, &blocked);
485 vg_assert(ir == 0);
486
487 /* pending = pending `intersect` blocked */
488 VG_(sigintersectset)(&pending, &blocked);
489
490 /* decide which signal we're going to snarf */
491 for (i = 1; i < _VKI_NSIG; i++)
492 if (VG_(sigismember)(&pending,i))
493 break;
494
495 if (i == _VKI_NSIG)
496 return 0;
497
498 if (debug)
499 VG_(debugLog)(0, "libcsignal",
500 "sigtimedwait_zero: snarfing signal %d\n", i );
501
502 /* fetch signal i.
503 pre: i is blocked and pending
504 pre: we are the only thread running
505 */
506 /* Set up alternative signal handler */
507 VG_(sigfillset)(&sa.sa_mask);
508 sa.ksa_handler = &sigtimedwait_zero_handler;
509 sa.sa_flags = 0;
510 ir = VG_(sigaction)(i, &sa, &saved_sa);
511 vg_assert(ir == 0);
512
513 /* Switch signal masks and wait for the signal. This should happen
514 immediately, since we've already established it is pending and
515 blocked. */
516 VG_(sigfillset)(&allbutone);
517 VG_(sigdelset)(&allbutone, i);
518 /* Note: pass the sig mask by value here, not reference (!) */
519 vg_assert(_VKI_NSIG_WORDS == 1);
520 sr = VG_(do_syscall3)(__NR_sigsuspend_nocancel,
521 (UWord)allbutone.sig[0], 0,0);
522 if (debug)
523 VG_(debugLog)(0, "libcsignal",
524 "sigtimedwait_zero: sigsuspend got "
525 "res: %s %#lx\n",
526 sr_isError(sr) ? "FAIL" : "SUCCESS",
527 sr_isError(sr) ? sr_Err(sr) : sr_Res(sr));
528 vg_assert(sr_isError(sr));
529 vg_assert(sr_Err(sr) == VKI_EINTR);
530
531 /* Restore signal's handler to whatever it was before */
532 VG_(convert_sigaction_fromK_to_toK)( &saved_sa, &saved_sa2 );
533 ir = VG_(sigaction)(i, &saved_sa2, NULL);
534 vg_assert(ir == 0);
535
536 /* This is bogus - we could get more info from the sighandler. */
537 VG_(memset)( info, 0, sizeof(*info) );
538 info->si_signo = i;
539
540 return i;
541}
542
sewardj8eb8bab2015-07-21 14:44:28 +0000543#elif defined(VGO_solaris)
544Int VG_(sigtimedwait_zero)( const vki_sigset_t *set, vki_siginfo_t *info )
545{
546 /* Trivial as on Linux. */
547 static const struct vki_timespec zero = { 0, 0 };
548 SysRes res = VG_(do_syscall3)(__NR_sigtimedwait, (UWord)set, (UWord)info,
549 (UWord)&zero);
550 return sr_isError(res) ? -1 : sr_Res(res);
551}
552
sewardj1383bdd2006-10-17 01:30:47 +0000553#else
njnf76d27a2009-05-28 01:53:07 +0000554# error "Unknown OS"
sewardj1383bdd2006-10-17 01:30:47 +0000555#endif
556
njnde62cbf2005-06-10 22:08:14 +0000557/*--------------------------------------------------------------------*/
558/*--- end ---*/
559/*--------------------------------------------------------------------*/