2 /*--------------------------------------------------------------------*/
3 /*--- Signal-related libc stuff. m_libcsignal.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2000-2013 Julian Seward
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.
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.
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
28 The GNU General Public License is contained in the file COPYING.
31 #include "pub_core_basics.h"
32 #include "pub_core_debuglog.h"
33 #include "pub_core_vki.h"
34 #include "pub_core_vkiscnums.h"
35 #include "pub_core_libcbase.h"
36 #include "pub_core_libcassert.h"
37 #include "pub_core_syscall.h"
38 #include "pub_core_libcsignal.h" /* self */
40 /* IMPORTANT: on Darwin it is essential to use the _nocancel versions
41 of syscalls rather than the vanilla version, if a _nocancel version
42 is available. See docs/internals/Darwin-notes.txt for the reason
45 /* sigemptyset, sigfullset, sigaddset and sigdelset return 0 on
46 success and -1 on error. */
47 /* In the sigset routines below, be aware that _VKI_NSIG_BPW can be
48 either 32 or 64, and hence the sig[] words can either be 32- or
49 64-bits. And which they are it doesn't necessarily follow from the
52 Int
VG_(sigfillset
)( vki_sigset_t
* set
)
57 for (i
= 0; i
< _VKI_NSIG_WORDS
; i
++)
62 Int
VG_(sigemptyset
)( vki_sigset_t
* set
)
67 for (i
= 0; i
< _VKI_NSIG_WORDS
; i
++)
72 Bool
VG_(isemptysigset
)( const vki_sigset_t
* set
)
75 vg_assert(set
!= NULL
);
76 for (i
= 0; i
< _VKI_NSIG_WORDS
; i
++)
77 if (set
->sig
[i
] != 0) return False
;
81 Bool
VG_(isfullsigset
)( const vki_sigset_t
* set
)
84 vg_assert(set
!= NULL
);
85 for (i
= 0; i
< _VKI_NSIG_WORDS
; i
++)
86 if (set
->sig
[i
] != ~0) return False
;
90 Bool
VG_(iseqsigset
)( const vki_sigset_t
* set1
, const vki_sigset_t
* set2
)
93 vg_assert(set1
!= NULL
&& set2
!= NULL
);
94 for (i
= 0; i
< _VKI_NSIG_WORDS
; i
++)
95 if (set1
->sig
[i
] != set2
->sig
[i
]) return False
;
100 Int
VG_(sigaddset
)( vki_sigset_t
* set
, Int signum
)
104 if (signum
< 1 || signum
> _VKI_NSIG
)
107 set
->sig
[signum
/ _VKI_NSIG_BPW
] |= (1ULL << (signum
% _VKI_NSIG_BPW
));
111 Int
VG_(sigdelset
)( vki_sigset_t
* set
, Int signum
)
115 if (signum
< 1 || signum
> _VKI_NSIG
)
118 set
->sig
[signum
/ _VKI_NSIG_BPW
] &= ~(1ULL << (signum
% _VKI_NSIG_BPW
));
122 Int
VG_(sigismember
) ( const vki_sigset_t
* set
, Int signum
)
126 if (signum
< 1 || signum
> _VKI_NSIG
)
129 if (1 & ((set
->sig
[signum
/ _VKI_NSIG_BPW
]) >> (signum
% _VKI_NSIG_BPW
)))
135 /* Add all signals in src to dst. */
136 void VG_(sigaddset_from_set
)( vki_sigset_t
* dst
, const vki_sigset_t
* src
)
139 vg_assert(dst
!= NULL
&& src
!= NULL
);
140 for (i
= 0; i
< _VKI_NSIG_WORDS
; i
++)
141 dst
->sig
[i
] |= src
->sig
[i
];
144 /* Remove all signals in src from dst. */
145 void VG_(sigdelset_from_set
)( vki_sigset_t
* dst
, const vki_sigset_t
* src
)
148 vg_assert(dst
!= NULL
&& src
!= NULL
);
149 for (i
= 0; i
< _VKI_NSIG_WORDS
; i
++)
150 dst
->sig
[i
] &= ~(src
->sig
[i
]);
153 /* dst = dst `intersect` src. */
154 void VG_(sigintersectset
)( vki_sigset_t
* dst
, const vki_sigset_t
* src
)
157 vg_assert(dst
!= NULL
&& src
!= NULL
);
158 for (i
= 0; i
< _VKI_NSIG_WORDS
; i
++)
159 dst
->sig
[i
] &= src
->sig
[i
];
163 void VG_(sigcomplementset
)( vki_sigset_t
* dst
, const vki_sigset_t
* src
)
166 vg_assert(dst
!= NULL
&& src
!= NULL
);
167 for (i
= 0; i
< _VKI_NSIG_WORDS
; i
++)
168 dst
->sig
[i
] = ~ src
->sig
[i
];
172 /* The functions sigaction, sigprocmask, sigpending and sigsuspend
173 return 0 on success and -1 on error.
175 Int
VG_(sigprocmask
)( Int how
, const vki_sigset_t
* set
, vki_sigset_t
* oldset
)
177 # if defined(VGO_linux)
178 # if defined(__NR_rt_sigprocmask)
179 SysRes res
= VG_(do_syscall4
)(__NR_rt_sigprocmask
,
180 how
, (UWord
)set
, (UWord
)oldset
,
181 _VKI_NSIG_WORDS
* sizeof(UWord
));
183 SysRes res
= VG_(do_syscall3
)(__NR_sigprocmask
,
184 how
, (UWord
)set
, (UWord
)oldset
);
187 # elif defined(VGO_darwin)
188 /* On Darwin, __NR_sigprocmask appears to affect the entire
189 process, not just this thread. Hence need to use
190 __NR___pthread_sigmask instead. */
191 SysRes res
= VG_(do_syscall3
)(__NR___pthread_sigmask
,
192 how
, (UWord
)set
, (UWord
)oldset
);
196 return sr_isError(res
) ? -1 : 0;
200 #if defined(VGO_darwin)
201 /* A helper function for sigaction on Darwin. */
203 void darwin_signal_demux(void* a1
, UWord a2
, UWord a3
, void* a4
, void* a5
) {
204 VG_(debugLog
)(2, "libcsignal",
205 "PRE demux sig, a2 = %lu, signo = %lu\n", a2
, a3
);
207 ((void(*)(int))a1
) (a3
);
209 ((void(*)(int,void*,void*))a1
) (a3
,a4
,a5
);
210 VG_(debugLog
)(2, "libcsignal",
211 "POST demux sig, a2 = %lu, signo = %lu\n", a2
, a3
);
212 VG_(do_syscall2
)(__NR_sigreturn
, (UWord
)a5
, 0x1E);
214 __asm__
__volatile__("ud2");
218 Int
VG_(sigaction
) ( Int signum
,
219 const vki_sigaction_toK_t
* act
,
220 vki_sigaction_fromK_t
* oldact
)
222 # if defined(VGO_linux)
223 /* Normal case: vki_sigaction_toK_t and vki_sigaction_fromK_t are
225 SysRes res
= VG_(do_syscall4
)(__NR_rt_sigaction
,
226 signum
, (UWord
)act
, (UWord
)oldact
,
227 _VKI_NSIG_WORDS
* sizeof(UWord
));
228 return sr_isError(res
) ? -1 : 0;
230 # elif defined(VGO_darwin)
231 /* If we're passing a new action to the kernel, make a copy of the
232 new action, install our own sa_tramp field in it, and ignore
233 whatever we were provided with. This is OK because all the
234 sigaction requests come from m_signals, and are not directly
235 what the client program requested, so there is no chance that we
236 will inadvertantly ignore the sa_tramp field requested by the
237 client. (In fact m_signals does ignore it when building signal
238 frames for the client, but that's a completely different
241 If we're receiving an old action from the kernel, be very
242 paranoid and make sure the kernel doesn't trash bits of memory
243 that we don't expect it to. */
246 vki_sigaction_toK_t actCopy
;
249 vki_sigaction_fromK_t oa
;
254 vki_sigaction_toK_t
* real_act
;
255 vki_sigaction_fromK_t
* real_oldact
;
257 real_act
= act
? &actCopy
: NULL
;
258 real_oldact
= oldact
? &oldactCopy
.oa
: NULL
;
259 VG_(memset
)(&oldactCopy
, 0x55, sizeof(oldactCopy
));
262 real_act
->sa_tramp
= (void*)&darwin_signal_demux
;
264 res
= VG_(do_syscall3
)(__NR_sigaction
,
265 signum
, (UWord
)real_act
, (UWord
)real_oldact
);
267 vg_assert(oldactCopy
.before
[0] == 0x5555555555555555ULL
);
268 vg_assert(oldactCopy
.before
[1] == 0x5555555555555555ULL
);
269 vg_assert(oldactCopy
.after
[0] == 0x5555555555555555ULL
);
270 vg_assert(oldactCopy
.after
[1] == 0x5555555555555555ULL
);
271 *oldact
= *real_oldact
;
273 return sr_isError(res
) ? -1 : 0;
276 # error "Unsupported OS"
281 /* See explanation in pub_core_libcsignal.h. */
283 VG_(convert_sigaction_fromK_to_toK
)( const vki_sigaction_fromK_t
* fromK
,
284 /*OUT*/vki_sigaction_toK_t
* toK
)
286 # if defined(VGO_linux)
288 # elif defined(VGO_darwin)
289 toK
->ksa_handler
= fromK
->ksa_handler
;
290 toK
->sa_tramp
= NULL
; /* the cause of all the difficulty */
291 toK
->sa_mask
= fromK
->sa_mask
;
292 toK
->sa_flags
= fromK
->sa_flags
;
294 # error "Unsupported OS"
299 Int
VG_(kill
)( Int pid
, Int signo
)
301 # if defined(VGO_linux)
302 SysRes res
= VG_(do_syscall2
)(__NR_kill
, pid
, signo
);
303 # elif defined(VGO_darwin)
304 SysRes res
= VG_(do_syscall3
)(__NR_kill
,
305 pid
, signo
, 1/*posix-compliant*/);
307 # error "Unsupported OS"
309 return sr_isError(res
) ? -1 : 0;
312 Int
VG_(tkill
)( Int lwpid
, Int signo
)
314 # if defined(__NR_tkill)
315 SysRes res
= VG_(mk_SysRes_Error
)(VKI_ENOSYS
);
316 res
= VG_(do_syscall2
)(__NR_tkill
, lwpid
, signo
);
317 if (sr_isError(res
) && sr_Err(res
) == VKI_ENOSYS
)
318 res
= VG_(do_syscall2
)(__NR_kill
, lwpid
, signo
);
319 return sr_isError(res
) ? -1 : 0;
321 # elif defined(VGO_darwin)
322 // Note that the __pthread_kill syscall takes a Mach thread, not a pthread.
324 res
= VG_(do_syscall2
)(__NR___pthread_kill
, lwpid
, signo
);
325 return sr_isError(res
) ? -1 : 0;
328 # error "Unsupported plat"
332 /* ---------------------- sigtimedwait_zero ----------------------- */
334 /* A cut-down version of POSIX sigtimedwait: poll for pending signals
335 mentioned in the sigset_t, and if any are present, select one
336 arbitrarily, return its number (which must be > 0), and put
337 auxiliary info about it in the siginfo_t, and make it
338 not-pending-any-more. If none are pending, return zero. The _zero
339 refers to the fact that there is zero timeout, so if no signals are
340 pending it returns immediately. Perhaps a better name would be
341 'sigpoll'. Returns -1 on error, 0 if no signals pending, and n > 0
342 if signal n was selected.
344 The Linux implementation is trivial: do the corresponding syscall.
346 The Darwin implementation is horrible and probably broken in a dozen
347 obscure ways. I suspect it's only thread-safe because V forces
348 single-threadedness. */
350 /* ---------- sigtimedwait_zero: Linux ----------- */
352 #if defined(VGO_linux)
353 Int
VG_(sigtimedwait_zero
)( const vki_sigset_t
*set
,
354 vki_siginfo_t
*info
)
356 static const struct vki_timespec zero
= { 0, 0 };
357 SysRes res
= VG_(do_syscall4
)(__NR_rt_sigtimedwait
, (UWord
)set
, (UWord
)info
,
358 (UWord
)&zero
, sizeof(*set
));
359 return sr_isError(res
) ? -1 : sr_Res(res
);
362 /* ---------- sigtimedwait_zero: Darwin ----------- */
364 #elif defined(VGO_darwin)
366 //static void show_set ( HChar* str, const vki_sigset_t* set ) {
368 // VG_(printf)("%s { ", str);
369 // for (i = 1; i <= _VKI_NSIG; i++) {
370 // if (VG_(sigismember)(set, i))
371 // VG_(printf)("%u ", i);
373 // VG_(printf)("}\n");
376 /* The general idea is:
377 - use sigpending to find out which signals are pending
379 - temporarily set its handler to sigtimedwait_zero_handler
380 - use sigsuspend atomically unblock it and wait for the signal.
381 Upon return, sigsuspend restores the signal mask to what it
383 - Restore the handler for the signal to whatever it was before.
386 /* A signal handler which does nothing (it doesn't need to). It does
387 however check that it's not handing a sync signal for which
388 returning is meaningless. */
389 static void sigtimedwait_zero_handler ( Int sig
)
391 /* XXX this is wrong -- get rid of these. We could
392 get _any_ signal here */
393 vg_assert(sig
!= VKI_SIGILL
);
394 vg_assert(sig
!= VKI_SIGSEGV
);
395 vg_assert(sig
!= VKI_SIGBUS
);
396 vg_assert(sig
!= VKI_SIGTRAP
);
400 Int
VG_(sigtimedwait_zero
)( const vki_sigset_t
*set
,
401 vki_siginfo_t
*info
)
403 const Bool debug
= False
;
406 vki_sigset_t pending
, blocked
, allbutone
;
407 vki_sigaction_toK_t sa
, saved_sa2
;
408 vki_sigaction_fromK_t saved_sa
;
410 //show_set("STWZ: looking for", set);
412 /* Find out what's pending: Darwin sigpending */
413 sr
= VG_(do_syscall1
)(__NR_sigpending
, (UWord
)&pending
);
414 vg_assert(!sr_isError(sr
));
416 /* don't try for signals not in 'set' */
417 /* pending = pending `intersect` set */
418 VG_(sigintersectset
)(&pending
, (vki_sigset_t
*)set
);
420 /* don't try for signals not blocked at the moment */
421 ir
= VG_(sigprocmask
)(VKI_SIG_SETMASK
, NULL
, &blocked
);
424 /* pending = pending `intersect` blocked */
425 VG_(sigintersectset
)(&pending
, &blocked
);
427 /* decide which signal we're going to snarf */
428 for (i
= 1; i
< _VKI_NSIG
; i
++)
429 if (VG_(sigismember
)(&pending
,i
))
436 VG_(debugLog
)(0, "libcsignal",
437 "sigtimedwait_zero: snarfing signal %d\n", i
);
440 pre: i is blocked and pending
441 pre: we are the only thread running
443 /* Set up alternative signal handler */
444 VG_(sigfillset
)(&sa
.sa_mask
);
445 sa
.ksa_handler
= &sigtimedwait_zero_handler
;
447 ir
= VG_(sigaction
)(i
, &sa
, &saved_sa
);
450 /* Switch signal masks and wait for the signal. This should happen
451 immediately, since we've already established it is pending and
453 VG_(sigfillset
)(&allbutone
);
454 VG_(sigdelset
)(&allbutone
, i
);
455 /* Note: pass the sig mask by value here, not reference (!) */
456 vg_assert(_VKI_NSIG_WORDS
== 1);
457 sr
= VG_(do_syscall3
)(__NR_sigsuspend_nocancel
,
458 (UWord
)allbutone
.sig
[0], 0,0);
460 VG_(debugLog
)(0, "libcsignal",
461 "sigtimedwait_zero: sigsuspend got "
463 sr_isError(sr
) ? "FAIL" : "SUCCESS",
464 sr_isError(sr
) ? sr_Err(sr
) : sr_Res(sr
));
465 vg_assert(sr_isError(sr
));
466 vg_assert(sr_Err(sr
) == VKI_EINTR
);
468 /* Restore signal's handler to whatever it was before */
469 VG_(convert_sigaction_fromK_to_toK
)( &saved_sa
, &saved_sa2
);
470 ir
= VG_(sigaction
)(i
, &saved_sa2
, NULL
);
473 /* This is bogus - we could get more info from the sighandler. */
474 VG_(memset
)( info
, 0, sizeof(*info
) );
484 /*--------------------------------------------------------------------*/
486 /*--------------------------------------------------------------------*/