m_libcsignal.c revision f76d27a697a7b0bf3b84490baf60623fc96a23af
1
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
10   Copyright (C) 2000-2009 Julian Seward
11      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
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 */
39
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
43   why. */
44
45/* sigemptyset, sigfullset, sigaddset and sigdelset return 0 on
46   success and -1 on error.  */
47/* I believe the indexing scheme in ->sig[] is also correct for
48   32- and 64-bit AIX (verified 27 July 06). */
49/* In the sigset routines below, be aware that _VKI_NSIG_BPW can be
50   either 32 or 64, and hence the sig[] words can either be 32- or
51   64-bits.  And which they are it doesn't necessarily follow from the
52   host word size. */
53
54Int VG_(sigfillset)( vki_sigset_t* set )
55{
56   Int i;
57   if (set == NULL)
58      return -1;
59   for (i = 0; i < _VKI_NSIG_WORDS; i++)
60      set->sig[i] = ~0;
61   return 0;
62}
63
64Int VG_(sigemptyset)( vki_sigset_t* set )
65{
66   Int i;
67   if (set == NULL)
68      return -1;
69   for (i = 0; i < _VKI_NSIG_WORDS; i++)
70      set->sig[i] = 0;
71   return 0;
72}
73
74Bool VG_(isemptysigset)( const vki_sigset_t* set )
75{
76   Int i;
77   vg_assert(set != NULL);
78   for (i = 0; i < _VKI_NSIG_WORDS; i++)
79      if (set->sig[i] != 0) return False;
80   return True;
81}
82
83Bool VG_(isfullsigset)( const vki_sigset_t* set )
84{
85   Int i;
86   vg_assert(set != NULL);
87   for (i = 0; i < _VKI_NSIG_WORDS; i++)
88      if (set->sig[i] != ~0) return False;
89   return True;
90}
91
92Bool VG_(iseqsigset)( const vki_sigset_t* set1, const vki_sigset_t* set2 )
93{
94   Int i;
95   vg_assert(set1 != NULL && set2 != NULL);
96   for (i = 0; i < _VKI_NSIG_WORDS; i++)
97      if (set1->sig[i] != set2->sig[i]) return False;
98   return True;
99}
100
101
102Int VG_(sigaddset)( vki_sigset_t* set, Int signum )
103{
104   if (set == NULL)
105      return -1;
106   if (signum < 1 || signum > _VKI_NSIG)
107      return -1;
108   signum--;
109   set->sig[signum / _VKI_NSIG_BPW] |= (1ULL << (signum % _VKI_NSIG_BPW));
110   return 0;
111}
112
113Int VG_(sigdelset)( vki_sigset_t* set, Int signum )
114{
115   if (set == NULL)
116      return -1;
117   if (signum < 1 || signum > _VKI_NSIG)
118      return -1;
119   signum--;
120   set->sig[signum / _VKI_NSIG_BPW] &= ~(1ULL << (signum % _VKI_NSIG_BPW));
121   return 0;
122}
123
124Int VG_(sigismember) ( const vki_sigset_t* set, Int signum )
125{
126   if (set == NULL)
127      return 0;
128   if (signum < 1 || signum > _VKI_NSIG)
129      return 0;
130   signum--;
131   if (1 & ((set->sig[signum / _VKI_NSIG_BPW]) >> (signum % _VKI_NSIG_BPW)))
132      return 1;
133   else
134      return 0;
135}
136
137/* Add all signals in src to dst. */
138void VG_(sigaddset_from_set)( vki_sigset_t* dst, vki_sigset_t* src )
139{
140   Int i;
141   vg_assert(dst != NULL && src != NULL);
142   for (i = 0; i < _VKI_NSIG_WORDS; i++)
143      dst->sig[i] |= src->sig[i];
144}
145
146/* Remove all signals in src from dst. */
147void VG_(sigdelset_from_set)( vki_sigset_t* dst, vki_sigset_t* src )
148{
149   Int i;
150   vg_assert(dst != NULL && src != NULL);
151   for (i = 0; i < _VKI_NSIG_WORDS; i++)
152      dst->sig[i] &= ~(src->sig[i]);
153}
154
155/* dst = dst `intersect` src. */
156void VG_(sigintersectset)( vki_sigset_t* dst, vki_sigset_t* src )
157{
158   Int i;
159   vg_assert(dst != NULL && src != NULL);
160   for (i = 0; i < _VKI_NSIG_WORDS; i++)
161      dst->sig[i] &= src->sig[i];
162}
163
164/* dst = ~src */
165void VG_(sigcomplementset)( vki_sigset_t* dst, vki_sigset_t* src )
166{
167   Int i;
168   vg_assert(dst != NULL && src != NULL);
169   for (i = 0; i < _VKI_NSIG_WORDS; i++)
170      dst->sig[i] = ~ src->sig[i];
171}
172
173
174/* The functions sigaction, sigprocmask, sigpending and sigsuspend
175   return 0 on success and -1 on error.
176*/
177Int VG_(sigprocmask)( Int how, const vki_sigset_t* set, vki_sigset_t* oldset)
178{
179#  if defined(VGO_linux) || defined(VGO_aix5)
180#  if defined(__NR_rt_sigprocmask)
181   SysRes res = VG_(do_syscall4)(__NR_rt_sigprocmask,
182                                 how, (UWord)set, (UWord)oldset,
183                                 _VKI_NSIG_WORDS * sizeof(UWord));
184#  else
185   SysRes res = VG_(do_syscall3)(__NR_sigprocmask,
186                                 how, (UWord)set, (UWord)oldset);
187#  endif
188
189#  elif defined(VGO_darwin)
190   /* On Darwin, __NR_sigprocmask appears to affect the entire
191      process, not just this thread.  Hence need to use
192      __NR___pthread_sigmask instead. */
193   SysRes res =  VG_(do_syscall3)(__NR___pthread_sigmask,
194                                  how, (UWord)set, (UWord)oldset);
195#  else
196#    error "Unknown OS"
197#  endif
198   return sr_isError(res) ? -1 : 0;
199}
200
201
202#if defined(VGO_darwin)
203/* A helper function for sigaction on Darwin. */
204static
205void darwin_signal_demux(void* a1, UWord a2, UWord a3, void* a4, void* a5) {
206   VG_(debugLog)(2, "libcsignal",
207                    "PRE  demux sig, a2 = %lu, signo = %lu\n", a2, a3);
208   if (a2 == 1)
209      ((void(*)(int))a1) (a3);
210   else
211      ((void(*)(int,void*,void*))a1) (a3,a4,a5);
212   VG_(debugLog)(2, "libcsignal",
213                    "POST demux sig, a2 = %lu, signo = %lu\n", a2, a3);
214   VG_(do_syscall2)(__NR_sigreturn, (UWord)a5, 0x1E);
215   /* NOTREACHED */
216   __asm__ __volatile__("ud2");
217}
218#endif
219
220Int VG_(sigaction) ( Int signum,
221                     const vki_sigaction_toK_t* act,
222                     vki_sigaction_fromK_t* oldact)
223{
224#  if defined(VGO_linux) || defined(VGO_aix5)
225   /* Normal case: vki_sigaction_toK_t and vki_sigaction_fromK_t are
226      identical types. */
227   SysRes res = VG_(do_syscall4)(__NR_rt_sigaction,
228                                 signum, (UWord)act, (UWord)oldact,
229                                 _VKI_NSIG_WORDS * sizeof(UWord));
230   return sr_isError(res) ? -1 : 0;
231
232#  elif defined(VGO_darwin)
233   /* If we're passing a new action to the kernel, make a copy of the
234      new action, install our own sa_tramp field in it, and ignore
235      whatever we were provided with.  This is OK because all the
236      sigaction requests come from m_signals, and are not directly
237      what the client program requested, so there is no chance that we
238      will inadvertantly ignore the sa_tramp field requested by the
239      client.  (In fact m_signals does ignore it when building signal
240      frames for the client, but that's a completely different
241      matter).
242
243      If we're receiving an old action from the kernel, be very
244      paranoid and make sure the kernel doesn't trash bits of memory
245      that we don't expect it to. */
246   SysRes res;
247
248   vki_sigaction_toK_t actCopy;
249   struct {
250     ULong before[2];
251     vki_sigaction_fromK_t oa;
252     ULong after[2];
253   }
254   oldactCopy;
255
256   vki_sigaction_toK_t*   real_act;
257   vki_sigaction_fromK_t* real_oldact;
258
259   real_act    = act    ? &actCopy       : NULL;
260   real_oldact = oldact ? &oldactCopy.oa : NULL;
261   VG_(memset)(&oldactCopy, 0x55, sizeof(oldactCopy));
262   if (real_act) {
263      *real_act = *act;
264      real_act->sa_tramp = (void*)&darwin_signal_demux;
265   }
266   res = VG_(do_syscall3)(__NR_sigaction,
267                          signum, (UWord)real_act, (UWord)real_oldact);
268   if (real_oldact) {
269      vg_assert(oldactCopy.before[0] == 0x5555555555555555ULL);
270      vg_assert(oldactCopy.before[1] == 0x5555555555555555ULL);
271      vg_assert(oldactCopy.after[0]  == 0x5555555555555555ULL);
272      vg_assert(oldactCopy.after[1]  == 0x5555555555555555ULL);
273      *oldact = *real_oldact;
274   }
275   return sr_isError(res) ? -1 : 0;
276
277#  else
278#    error "Unsupported OS"
279#  endif
280}
281
282
283/* See explanation in pub_core_libcsignal.h. */
284void
285VG_(convert_sigaction_fromK_to_toK)( vki_sigaction_fromK_t* fromK,
286                                     /*OUT*/vki_sigaction_toK_t* toK )
287{
288#  if defined(VGO_linux) || defined(VGO_aix5)
289   *toK = *fromK;
290#  elif defined(VGO_darwin)
291   toK->ksa_handler = fromK->ksa_handler;
292   toK->sa_tramp    = NULL; /* the cause of all the difficulty */
293   toK->sa_mask     = fromK->sa_mask;
294   toK->sa_flags    = fromK->sa_flags;
295#  else
296#    error "Unsupported OS"
297#  endif
298}
299
300
301Int VG_(kill)( Int pid, Int signo )
302{
303#  if defined(VGO_linux) || defined(VGO_aix5)
304   SysRes res = VG_(do_syscall2)(__NR_kill, pid, signo);
305#  elif defined(VGO_darwin)
306   SysRes res = VG_(do_syscall3)(__NR_kill,
307                                 pid, signo, 1/*posix-compliant*/);
308#  else
309#    error "Unsupported OS"
310#  endif
311   return sr_isError(res) ? -1 : 0;
312}
313
314Int VG_(tkill)( Int lwpid, Int signo )
315{
316#  if defined(__NR_tkill)
317   SysRes res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
318   res = VG_(do_syscall2)(__NR_tkill, lwpid, signo);
319   if (sr_isError(res) && sr_Err(res) == VKI_ENOSYS)
320      res = VG_(do_syscall2)(__NR_kill, lwpid, signo);
321   return sr_isError(res) ? -1 : 0;
322
323#  elif defined(VGO_darwin)
324   // Note that the __pthread_kill syscall takes a Mach thread, not a pthread.
325   SysRes res;
326   res = VG_(do_syscall2)(__NR___pthread_kill, lwpid, signo);
327   return sr_isError(res) ? -1 : 0;
328
329#  else
330#    error "Unsupported plat"
331#  endif
332}
333
334/* ---------------------- sigtimedwait_zero ----------------------- */
335
336/* A cut-down version of POSIX sigtimedwait: poll for pending signals
337   mentioned in the sigset_t, and if any are present, select one
338   arbitrarily, return its number (which must be > 0), and put
339   auxiliary info about it in the siginfo_t, and make it
340   not-pending-any-more.  If none are pending, return zero.  The _zero
341   refers to the fact that there is zero timeout, so if no signals are
342   pending it returns immediately.  Perhaps a better name would be
343   'sigpoll'.  Returns -1 on error, 0 if no signals pending, and n > 0
344   if signal n was selected.
345
346   The Linux implementation is trivial: do the corresponding syscall.
347
348   The AIX implementation is horrible and probably broken in a dozen
349   obscure ways.  I suspect it's only thread-safe because V forces
350   single-threadedness. */
351
352/* ---------- sigtimedwait_zero: Linux ----------- */
353
354#if defined(VGO_linux)
355Int VG_(sigtimedwait_zero)( const vki_sigset_t *set,
356                            vki_siginfo_t *info )
357{
358   static const struct vki_timespec zero = { 0, 0 };
359   SysRes res = VG_(do_syscall4)(__NR_rt_sigtimedwait, (UWord)set, (UWord)info,
360                                 (UWord)&zero, sizeof(*set));
361   return sr_isError(res) ? -1 : sr_Res(res);
362}
363
364/* ---------- sigtimedwait_zero: AIX5 ----------- */
365
366#elif defined(VGO_aix5)
367/* The general idea is:
368   - use sigpending to find out which signals are pending
369   - choose one
370   - temporarily set its handler to sigtimedwait_zero_handler
371   - use sigsuspend atomically unblock it and wait for the signal.
372     Upon return, sigsuspend restores the signal mask to what it
373     was to start with.
374   - Restore the handler for the signal to whatever it was before.
375*/
376
377/* A signal handler which does nothing (it doesn't need to).  It does
378   however check that it's not handing a sync signal for which
379   returning is meaningless. */
380static void sigtimedwait_zero_handler ( Int sig )
381{
382   vg_assert(sig != VKI_SIGILL);
383   vg_assert(sig != VKI_SIGSEGV);
384   vg_assert(sig != VKI_SIGBUS);
385   vg_assert(sig != VKI_SIGTRAP);
386   /* do nothing */
387}
388
389Int VG_(sigtimedwait_zero)( const vki_sigset_t *set,
390                            vki_siginfo_t *info )
391{
392  Int    i, ir;
393  SysRes sr;
394  vki_sigset_t pending, blocked, allbutone;
395  struct vki_sigaction sa, saved_sa;
396
397  /* Find out what's pending: AIX _sigpending */
398  sr = VG_(do_syscall1)(__NR__sigpending, (UWord)&pending);
399  vg_assert(!sr.isError);
400
401  /* don't try for signals not in 'set' */
402  /* pending = pending `intersect` set */
403  VG_(sigintersectset)(&pending, set);
404
405  /* don't try for signals not blocked at the moment */
406  ir = VG_(sigprocmask)(VKI_SIG_SETMASK, NULL, &blocked);
407  vg_assert(ir == 0);
408
409  /* pending = pending `intersect` blocked */
410  VG_(sigintersectset)(&pending, blocked);
411
412  /* decide which signal we're going to snarf */
413  for (i = 1; i < _VKI_NSIG; i++)
414     if (VG_(sigismember)(&pending,i))
415        break;
416
417  if (i == _VKI_NSIG)
418     return 0;
419
420  /* fetch signal i.
421     pre: i is blocked and pending
422     pre: we are the only thread running
423  */
424  /* Set up alternative signal handler */
425  VG_(sigfillset)(&allbutone);
426  VG_(sigdelset)(&allbutone, i);
427  sa.sa_mask     = allbutone;
428  sa.ksa_handler = &sigtimedwait_zero_handler;
429  sa.sa_flags    = 0;
430  ir = VG_(sigaction)(i, &sa, &saved_sa);
431  vg_assert(ir == 0);
432
433  /* Switch signal masks and wait for the signal.  This should happen
434     immediately, since we've already established it is pending and
435     blocked. */
436  sr = VG_(do_syscall1)(__NR__sigsuspend, (UWord)&allbutone);
437  vg_assert(sr.isError);
438  if (0)
439     VG_(debugLog)(0, "libcsignal",
440                      "sigtimedwait_zero: sigsuspend got res %ld err %ld\n",
441                      sr.res, sr.err);
442  vg_assert(sr.res == (UWord)-1);
443
444  /* Restore signal's handler to whatever it was before */
445  ir = VG_(sigaction)(i, &saved_sa, NULL);
446  vg_assert(ir == 0);
447
448  /* This is bogus - we could get more info from the sighandler. */
449  VG_(memset)( info, 0, sizeof(*info) );
450  info->si_signo = i;
451
452  return i;
453}
454
455/* ---------- sigtimedwait_zero: Darwin ----------- */
456
457#elif defined(VGO_darwin)
458
459//static void show_set ( HChar* str, const vki_sigset_t* set ) {
460//   Int i;
461//   VG_(printf)("%s { ", str);
462//   for (i = 1; i <= _VKI_NSIG; i++) {
463//     if (VG_(sigismember)(set, i))
464//         VG_(printf)("%u ", i);
465//   }
466//   VG_(printf)("}\n");
467//}
468
469static void sigtimedwait_zero_handler ( Int sig )
470{
471   /* XXX this is wrong -- get rid of these.  We could
472      get _any_ signal here */
473   vg_assert(sig != VKI_SIGILL);
474   vg_assert(sig != VKI_SIGSEGV);
475   vg_assert(sig != VKI_SIGBUS);
476   vg_assert(sig != VKI_SIGTRAP);
477   /* do nothing */
478}
479
480Int VG_(sigtimedwait_zero)( const vki_sigset_t *set,
481                            vki_siginfo_t *info )
482{
483  const Bool debug = False;
484  Int    i, ir;
485  SysRes sr;
486  vki_sigset_t pending, blocked, allbutone;
487  vki_sigaction_toK_t   sa, saved_sa2;
488  vki_sigaction_fromK_t saved_sa;
489
490  //show_set("STWZ: looking for", set);
491
492  /* Find out what's pending: Darwin sigpending */
493  sr = VG_(do_syscall1)(__NR_sigpending, (UWord)&pending);
494  vg_assert(!sr_isError(sr));
495
496  /* don't try for signals not in 'set' */
497  /* pending = pending `intersect` set */
498  VG_(sigintersectset)(&pending, (vki_sigset_t*)set);
499
500  /* don't try for signals not blocked at the moment */
501  ir = VG_(sigprocmask)(VKI_SIG_SETMASK, NULL, &blocked);
502  vg_assert(ir == 0);
503
504  /* pending = pending `intersect` blocked */
505  VG_(sigintersectset)(&pending, &blocked);
506
507  /* decide which signal we're going to snarf */
508  for (i = 1; i < _VKI_NSIG; i++)
509     if (VG_(sigismember)(&pending,i))
510        break;
511
512  if (i == _VKI_NSIG)
513     return 0;
514
515  if (debug)
516     VG_(debugLog)(0, "libcsignal",
517                      "sigtimedwait_zero: snarfing signal %d\n", i );
518
519  /* fetch signal i.
520     pre: i is blocked and pending
521     pre: we are the only thread running
522  */
523  /* Set up alternative signal handler */
524  VG_(sigfillset)(&sa.sa_mask);
525  sa.ksa_handler = &sigtimedwait_zero_handler;
526  sa.sa_flags    = 0;
527  ir = VG_(sigaction)(i, &sa, &saved_sa);
528  vg_assert(ir == 0);
529
530  /* Switch signal masks and wait for the signal.  This should happen
531     immediately, since we've already established it is pending and
532     blocked. */
533  VG_(sigfillset)(&allbutone);
534  VG_(sigdelset)(&allbutone, i);
535  /* Note: pass the sig mask by value here, not reference (!) */
536  vg_assert(_VKI_NSIG_WORDS == 1);
537  sr = VG_(do_syscall3)(__NR_sigsuspend_nocancel,
538                        (UWord)allbutone.sig[0], 0,0);
539  if (debug)
540     VG_(debugLog)(0, "libcsignal",
541                      "sigtimedwait_zero: sigsuspend got "
542                      "res: %s %#lx\n",
543                      sr_isError(sr) ? "FAIL" : "SUCCESS",
544                      sr_isError(sr) ? sr_Err(sr) : sr_Res(sr));
545  vg_assert(sr_isError(sr));
546  vg_assert(sr_Err(sr) == VKI_EINTR);
547
548  /* Restore signal's handler to whatever it was before */
549  VG_(convert_sigaction_fromK_to_toK)( &saved_sa, &saved_sa2 );
550  ir = VG_(sigaction)(i, &saved_sa2, NULL);
551  vg_assert(ir == 0);
552
553  /* This is bogus - we could get more info from the sighandler. */
554  VG_(memset)( info, 0, sizeof(*info) );
555  info->si_signo = i;
556
557  return i;
558}
559
560#else
561#  error "Unknown OS"
562#endif
563
564/*--------------------------------------------------------------------*/
565/*--- end                                                          ---*/
566/*--------------------------------------------------------------------*/
567