blob: 4ac642bc6716aafe9f00936ea402ed8033b9e8df [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
3/*--- Implementation of POSIX signals. ---*/
4/*--- vg_signals.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
njnc9539842002-10-02 13:26:35 +00008 This file is part of Valgrind, an extensible x86 protected-mode
9 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +000010
njn0e1b5142003-04-15 14:58:06 +000011 Copyright (C) 2000-2003 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000012 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000013
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
njn25e49d8e72002-09-23 09:36:25 +000029 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000030*/
31
32
33#include "vg_include.h"
sewardjde4a1d02002-03-22 01:27:54 +000034#include "vg_unsafe.h"
sewardje12a45f2003-03-15 20:03:33 +000035
36/* Sidestep the normal check which disallows using valgrind.h
37 directly. */
38#define __VALGRIND_SOMESKIN_H
sewardj54cacf02002-04-12 23:24:59 +000039#include "valgrind.h" /* for VALGRIND_MAGIC_SEQUENCE */
sewardjde4a1d02002-03-22 01:27:54 +000040
sewardj018f7622002-05-15 21:13:39 +000041/* Define to give more sanity checking for signals. */
42#define DEBUG_SIGNALS
43
44
sewardjfa356512002-05-24 00:00:59 +000045/* KNOWN BUGS 24 May 02:
46
47 - A signal is not masked in its own handler. Neither are the
48 signals in the signal's blocking mask.
49
50 - There is only one pending set for the entire process, whereas
51 POSIX seems to require each thread have its own pending set.
52 This means that a signal can only be pending for one thread at
53 a time.
54
55 - The following causes an infinite loop: start Hugs, Feb 2001
56 version, and do Control-C at the prompt. There is an infinite
57 series of sigints delivered (to the client); but also seemingly
58 to valgrind, which is very strange. I don't know why.
59
60 Probably a lot more bugs which I haven't discovered yet.
61*/
62
63
sewardj018f7622002-05-15 21:13:39 +000064/* ---------------------------------------------------------------------
65 Forwards decls.
66 ------------------------------------------------------------------ */
67
68static void vg_oursignalhandler ( Int sigNo );
69
70
71/* ---------------------------------------------------------------------
72 HIGH LEVEL STUFF TO DO WITH SIGNALS: POLICY (MOSTLY)
73 ------------------------------------------------------------------ */
74
sewardjde4a1d02002-03-22 01:27:54 +000075/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +000076 Signal state for this process.
77 ------------------------------------------------------------------ */
78
sewardj018f7622002-05-15 21:13:39 +000079
sewardjb48e5002002-05-13 00:16:03 +000080/* Base-ment of these arrays[VKI_KNSIG].
81
82 Valid signal numbers are 1 .. VKI_KNSIG inclusive.
83 Rather than subtracting 1 for indexing these arrays, which
84 is tedious and error-prone, they are simply dimensioned 1 larger,
85 and entry [0] is not used.
86 */
87
sewardjb48e5002002-05-13 00:16:03 +000088
sewardj018f7622002-05-15 21:13:39 +000089/* -----------------------------------------------------
90 Static client signal state (SCSS). This is the state
91 that the client thinks it has the kernel in.
92 SCSS records verbatim the client's settings. These
93 are mashed around only when SKSS is calculated from it.
94 -------------------------------------------------- */
sewardjb48e5002002-05-13 00:16:03 +000095
sewardj018f7622002-05-15 21:13:39 +000096typedef
97 struct {
98 void* scss_handler; /* VKI_SIG_DFL or VKI_SIG_IGN or ptr to
99 client's handler */
100 UInt scss_flags;
101 vki_ksigset_t scss_mask;
102 void* scss_restorer; /* god knows; we ignore it. */
103 }
104 SCSS_Per_Signal;
sewardjb48e5002002-05-13 00:16:03 +0000105
sewardj018f7622002-05-15 21:13:39 +0000106typedef
107 struct {
sewardj2342c972002-05-22 23:34:20 +0000108 /* per-signal info */
sewardj018f7622002-05-15 21:13:39 +0000109 SCSS_Per_Signal scss_per_sig[1+VKI_KNSIG];
sewardj2342c972002-05-22 23:34:20 +0000110
111 /* Signal delivery stack, if any. */
112 vki_kstack_t altstack;
113
sewardj018f7622002-05-15 21:13:39 +0000114 /* Additional elements to SCSS not stored here:
115 - for each thread, the thread's blocking mask
116 - for each thread in WaitSIG, the set of waited-on sigs
117 */
118 }
119 SCSS;
sewardjb48e5002002-05-13 00:16:03 +0000120
sewardj018f7622002-05-15 21:13:39 +0000121static SCSS vg_scss;
122
123
124/* -----------------------------------------------------
125 Static kernel signal state (SKSS). This is the state
126 that we have the kernel in. It is computed from SCSS.
127 -------------------------------------------------- */
128
129/* Let's do:
130 sigprocmask assigns to all thread masks
131 so that at least everything is always consistent
132 Flags:
133 SA_NOCLDSTOP -- passed to kernel
134 SA_ONESHOT or SA_RESETHAND -- required; abort if not set
135 SA_RESTART -- we observe this but set our handlers always to restart
136 SA_NOMASK or SA_NODEFER -- required to not be set; abort if set
137 SA_ONSTACK -- currently not supported; abort if set.
sewardjb48e5002002-05-13 00:16:03 +0000138*/
sewardjde4a1d02002-03-22 01:27:54 +0000139
sewardj77e466c2002-04-14 02:29:29 +0000140
sewardj018f7622002-05-15 21:13:39 +0000141typedef
142 struct {
143 void* skss_handler; /* VKI_SIG_DFL or VKI_SIG_IGN
144 or ptr to our handler */
145 UInt skss_flags;
146 /* There is no skss_mask, since we know that we will always ask
147 for all signals to be blocked in our one-and-only
148 sighandler. */
149 /* Also there is no skss_restorer. */
150 }
151 SKSS_Per_Signal;
sewardjde4a1d02002-03-22 01:27:54 +0000152
sewardj018f7622002-05-15 21:13:39 +0000153typedef
154 struct {
155 SKSS_Per_Signal skss_per_sig[1+VKI_KNSIG];
156 vki_ksigset_t skss_sigmask; /* process' blocked signal mask */
157 }
158 SKSS;
159
160static SKSS vg_skss;
sewardjde4a1d02002-03-22 01:27:54 +0000161
sewardj2e93c502002-04-12 11:12:52 +0000162
sewardj018f7622002-05-15 21:13:39 +0000163/* -----------------------------------------------------
164 Dynamic client signal state (DCSS). This holds transient
165 information about state of client signals.
166 -------------------------------------------------- */
sewardjb48e5002002-05-13 00:16:03 +0000167
sewardj018f7622002-05-15 21:13:39 +0000168typedef
169 struct {
170 /* True iff a signal has been received but not yet passed to
171 client. */
172 Bool dcss_sigpending[1+VKI_KNSIG];
173 /* If sigpending[] is True, has meaning:
174 VG_INVALID_THREADID -- to be passed to any suitable thread
175 other -- to be passed only to the specified thread. */
176 ThreadId dcss_destthread[1+VKI_KNSIG];
177 }
178 DCSS;
sewardjb48e5002002-05-13 00:16:03 +0000179
sewardj018f7622002-05-15 21:13:39 +0000180static DCSS vg_dcss;
sewardjb48e5002002-05-13 00:16:03 +0000181
182
sewardj018f7622002-05-15 21:13:39 +0000183/* ---------------------------------------------------------------------
184 Compute the SKSS required by the current SCSS.
185 ------------------------------------------------------------------ */
186
sewardj4f29ddf2002-05-03 22:29:04 +0000187static
sewardj018f7622002-05-15 21:13:39 +0000188void pp_SKSS ( void )
189{
190 Int sig;
191 VG_(printf)("\n\nSKSS:\n");
192 for (sig = 1; sig <= VKI_KNSIG; sig++) {
193 VG_(printf)("sig %d: handler 0x%x, flags 0x%x\n", sig,
194 vg_skss.skss_per_sig[sig].skss_handler,
195 vg_skss.skss_per_sig[sig].skss_flags );
sewardj77e466c2002-04-14 02:29:29 +0000196
sewardj018f7622002-05-15 21:13:39 +0000197 }
198 VG_(printf)("Global sigmask (63 .. 0) = 0x%x 0x%x\n",
199 vg_skss.skss_sigmask.ws[1],
200 vg_skss.skss_sigmask.ws[0] );
201}
202
203static __inline__
204Bool is_WaitSIGd_by_any_thread ( Int sig )
205{
206 ThreadId tid;
207 for (tid = 1; tid < VG_N_THREADS; tid++) {
208 if (VG_(threads)[tid].status != VgTs_WaitSIG)
209 continue;
210 if (VG_(ksigismember)( &VG_(threads)[tid].sigs_waited_for, sig ))
211 return True;
212 }
213 return False;
214}
215
216static __inline__
217Bool is_blocked_by_all_threads ( Int sig )
218{
219 ThreadId tid;
220 for (tid = 1; tid < VG_N_THREADS; tid++) {
221 if (VG_(threads)[tid].status == VgTs_Empty)
222 continue;
223 if (! VG_(ksigismember)( &VG_(threads)[tid].sig_mask, sig ))
224 return False;
225 }
226 return True;
227}
228
229
230/* This is the core, clever bit. Computation is as follows:
231
232 For each signal
233 handler = if client has a handler, then our handler
234 else if is WaitSIG'd by any thread, then our handler
235 else if client is DFL, then DFL
236 else (client must be IGN) IGN
237
238 blocked = if is blocked by all threads and not WaitSIG'd by
239 any thread
240 then BLOCKED
241 else UNBLOCKED
242*/
243static
244void calculate_SKSS_from_SCSS ( SKSS* dst )
245{
246 Int sig;
247 void* skss_handler;
248 void* scss_handler;
249 Bool iz_WaitSIGd_by_any_thread;
250 Bool iz_blocked_by_all_threads;
251 Bool skss_blocked;
252 UInt scss_flags;
253 UInt skss_flags;
254
255 VG_(ksigemptyset)( &dst->skss_sigmask );
256
257 for (sig = 1; sig <= VKI_KNSIG; sig++) {
258
259 /* Calculate kernel handler and blockedness for sig, as per rules
260 in above comment. */
261
262 iz_WaitSIGd_by_any_thread = is_WaitSIGd_by_any_thread(sig);
263 iz_blocked_by_all_threads = is_blocked_by_all_threads(sig);
264
265 scss_handler = vg_scss.scss_per_sig[sig].scss_handler;
266 scss_flags = vg_scss.scss_per_sig[sig].scss_flags;
267
268 /* Restorer */
269 /*
270 Doesn't seem like we can spin this one.
271 if (vg_scss.scss_per_sig[sig].scss_restorer != NULL)
272 VG_(unimplemented)
273 ("sigactions with non-NULL .sa_restorer field");
274 */
275
276 /* Handler */
277
278 if (scss_handler != VKI_SIG_DFL && scss_handler != VKI_SIG_IGN) {
279 skss_handler = &vg_oursignalhandler;
280 } else
281 if (iz_WaitSIGd_by_any_thread) {
282 skss_handler = &vg_oursignalhandler;
283 } else
284 if (scss_handler == VKI_SIG_DFL) {
285 skss_handler = VKI_SIG_DFL;
286 }
287 else {
288 vg_assert(scss_handler == VKI_SIG_IGN);
289 skss_handler = VKI_SIG_IGN;
290 }
291
292 /* Blockfulness */
293
294 skss_blocked
295 = iz_blocked_by_all_threads && !iz_WaitSIGd_by_any_thread;
296
297 /* Flags */
298
299 skss_flags = 0;
300 /* SA_NOCLDSTOP: pass to kernel */
301 if (scss_flags & VKI_SA_NOCLDSTOP)
302 skss_flags |= VKI_SA_NOCLDSTOP;
303 /* SA_ONESHOT: ignore client setting */
304 /*
305 if (!(scss_flags & VKI_SA_ONESHOT))
306 VG_(unimplemented)
307 ("sigactions without SA_ONESHOT");
308 vg_assert(scss_flags & VKI_SA_ONESHOT);
309 skss_flags |= VKI_SA_ONESHOT;
310 */
311 /* SA_RESTART: ignore client setting and set for us */
312 skss_flags |= VKI_SA_RESTART;
313 /* SA_NOMASK: not allowed */
314 /*
315 .. well, ignore it.
316 if (scss_flags & VKI_SA_NOMASK)
317 VG_(unimplemented)
318 ("sigactions with SA_NOMASK");
319 vg_assert(!(scss_flags & VKI_SA_NOMASK));
320 */
sewardj2342c972002-05-22 23:34:20 +0000321 /* SA_ONSTACK: client setting is irrelevant here */
322 /*
sewardj018f7622002-05-15 21:13:39 +0000323 if (scss_flags & VKI_SA_ONSTACK)
324 VG_(unimplemented)
325 ("signals on an alternative stack (SA_ONSTACK)");
326 vg_assert(!(scss_flags & VKI_SA_ONSTACK));
sewardj2342c972002-05-22 23:34:20 +0000327 */
sewardj018f7622002-05-15 21:13:39 +0000328 /* ... but WE ask for on-stack ourselves ... */
329 skss_flags |= VKI_SA_ONSTACK;
330
331 /* Create SKSS entry for this signal. */
332
333 if (skss_blocked
334 && sig != VKI_SIGKILL && sig != VKI_SIGSTOP)
335 VG_(ksigaddset)( &dst->skss_sigmask, sig );
336
sewardj6a3c26e2002-05-23 17:09:43 +0000337 if (sig != VKI_SIGKILL && sig != VKI_SIGSTOP)
338 dst->skss_per_sig[sig].skss_handler = skss_handler;
339 else
340 dst->skss_per_sig[sig].skss_handler = VKI_SIG_DFL;
341
sewardj018f7622002-05-15 21:13:39 +0000342 dst->skss_per_sig[sig].skss_flags = skss_flags;
343 }
344
345 /* Sanity checks. */
346 vg_assert(dst->skss_per_sig[VKI_SIGKILL].skss_handler
347 == VKI_SIG_DFL);
348 vg_assert(dst->skss_per_sig[VKI_SIGSTOP].skss_handler
349 == VKI_SIG_DFL);
350 vg_assert(!VG_(ksigismember)( &dst->skss_sigmask, VKI_SIGKILL ));
351 vg_assert(!VG_(ksigismember)( &dst->skss_sigmask, VKI_SIGSTOP ));
352
353 if (0)
354 pp_SKSS();
355}
356
357
358/* ---------------------------------------------------------------------
359 After a possible SCSS change, update SKSS and the kernel itself.
360 ------------------------------------------------------------------ */
361
362/* IMPORTANT NOTE: to avoid race conditions, we must always enter here
363 with ALL KERNEL SIGNALS BLOCKED !
364*/
365void VG_(handle_SCSS_change) ( Bool force_update )
366{
367 Int res, sig;
368 SKSS skss_old;
369 vki_ksigaction ksa, ksa_old;
370
371# ifdef DEBUG_SIGNALS
372 vki_ksigset_t test_sigmask;
373 res = VG_(ksigprocmask)( VKI_SIG_SETMASK /*irrelevant*/,
374 NULL, &test_sigmask );
375 vg_assert(res == 0);
376 /* The kernel never says that SIGKILL or SIGSTOP are masked. It is
377 correct! So we fake it here for the purposes only of
378 assertion. */
379 VG_(ksigaddset)( &test_sigmask, VKI_SIGKILL );
380 VG_(ksigaddset)( &test_sigmask, VKI_SIGSTOP );
381 vg_assert(VG_(kisfullsigset)( &test_sigmask ));
382# endif
383
384 /* Remember old SKSS and calculate new one. */
385 skss_old = vg_skss;
386 calculate_SKSS_from_SCSS ( &vg_skss );
387
388 /* Compare the new SKSS entries vs the old ones, and update kernel
389 where they differ. */
390 for (sig = 1; sig <= VKI_KNSIG; sig++) {
391
392 /* Trying to do anything with SIGKILL is pointless; just ignore
393 it. */
394 if (sig == VKI_SIGKILL || sig == VKI_SIGSTOP)
395 continue;
396
397 /* Aside: take the opportunity to clean up DCSS: forget about any
398 pending signals directed at dead threads. */
399 if (vg_dcss.dcss_sigpending[sig]
400 && vg_dcss.dcss_destthread[sig] != VG_INVALID_THREADID) {
401 ThreadId tid = vg_dcss.dcss_destthread[sig];
402 vg_assert(VG_(is_valid_or_empty_tid)(tid));
403 if (VG_(threads)[tid].status == VgTs_Empty) {
404 vg_dcss.dcss_sigpending[sig] = False;
405 vg_dcss.dcss_destthread[sig] = VG_INVALID_THREADID;
406 if (VG_(clo_trace_signals))
407 VG_(message)(Vg_DebugMsg,
408 "discarding pending signal %d due to thread %d exiting",
409 sig, tid );
410 }
411 }
412
413 /* End of the Aside. Now the Main Business. */
414
415 if (!force_update) {
416 if ((skss_old.skss_per_sig[sig].skss_handler
417 == vg_skss.skss_per_sig[sig].skss_handler)
418 && (skss_old.skss_per_sig[sig].skss_flags
419 == vg_skss.skss_per_sig[sig].skss_flags))
420 /* no difference */
421 continue;
422 }
423
424 ksa.ksa_handler = vg_skss.skss_per_sig[sig].skss_handler;
425 ksa.ksa_flags = vg_skss.skss_per_sig[sig].skss_flags;
426 vg_assert(ksa.ksa_flags & VKI_SA_ONSTACK);
427 VG_(ksigfillset)( &ksa.ksa_mask );
428 VG_(ksigdelset)( &ksa.ksa_mask, VKI_SIGKILL );
429 VG_(ksigdelset)( &ksa.ksa_mask, VKI_SIGSTOP );
430 ksa.ksa_restorer = NULL;
431
432 if (VG_(clo_trace_signals))
433 VG_(message)(Vg_DebugMsg,
434 "setting ksig %d to: hdlr 0x%x, flags 0x%x, "
435 "mask(63..0) 0x%x 0x%x",
436 sig, ksa.ksa_handler,
437 ksa.ksa_flags,
438 ksa.ksa_mask.ws[1],
439 ksa.ksa_mask.ws[0]
440 );
441
442 res = VG_(ksigaction)( sig, &ksa, &ksa_old );
443 vg_assert(res == 0);
444
445 /* Since we got the old sigaction more or less for free, might
446 as well extract the maximum sanity-check value from it. */
447 if (!force_update) {
448 vg_assert(ksa_old.ksa_handler
449 == skss_old.skss_per_sig[sig].skss_handler);
450 vg_assert(ksa_old.ksa_flags
451 == skss_old.skss_per_sig[sig].skss_flags);
452 vg_assert(ksa_old.ksa_restorer
453 == NULL);
454 VG_(ksigaddset)( &ksa_old.ksa_mask, VKI_SIGKILL );
455 VG_(ksigaddset)( &ksa_old.ksa_mask, VKI_SIGSTOP );
456 vg_assert(VG_(kisfullsigset)( &ksa_old.ksa_mask ));
457 }
458 }
459
460 /* Just set the new sigmask, even if it's no different from the
461 old, since we have to do this anyway, to unblock the host
462 signals. */
463 if (VG_(clo_trace_signals))
464 VG_(message)(Vg_DebugMsg,
465 "setting kmask(63..0) to 0x%x 0x%x",
466 vg_skss.skss_sigmask.ws[1],
467 vg_skss.skss_sigmask.ws[0]
468 );
469
470 VG_(restore_all_host_signals)( &vg_skss.skss_sigmask );
471}
472
473
474/* ---------------------------------------------------------------------
475 Update/query SCSS in accordance with client requests.
476 ------------------------------------------------------------------ */
477
sewardj2342c972002-05-22 23:34:20 +0000478/* Logic for this alt-stack stuff copied directly from do_sigaltstack
479 in kernel/signal.[ch] */
480
481/* True if we are on the alternate signal stack. */
482static Int on_sig_stack ( Addr m_esp )
483{
484 return (m_esp - (Addr)vg_scss.altstack.ss_sp
485 < vg_scss.altstack.ss_size);
486}
487
488static Int sas_ss_flags ( Addr m_esp )
489{
490 return (vg_scss.altstack.ss_size == 0
491 ? VKI_SS_DISABLE
492 : on_sig_stack(m_esp) ? VKI_SS_ONSTACK : 0);
493}
494
495
496void VG_(do__NR_sigaltstack) ( ThreadId tid )
497{
498 vki_kstack_t* ss;
499 vki_kstack_t* oss;
500 Addr m_esp;
501
502 vg_assert(VG_(is_valid_tid)(tid));
503 ss = (vki_kstack_t*)(VG_(threads)[tid].m_ebx);
504 oss = (vki_kstack_t*)(VG_(threads)[tid].m_ecx);
505 m_esp = VG_(threads)[tid].m_esp;
506
507 if (VG_(clo_trace_signals))
508 VG_(message)(Vg_DebugExtraMsg,
509 "__NR_sigaltstack: tid %d, "
510 "ss 0x%x, oss 0x%x (current %%esp %p)",
511 tid, (UInt)ss, (UInt)oss, (UInt)m_esp );
512
513 if (oss != NULL) {
514 oss->ss_sp = vg_scss.altstack.ss_sp;
515 oss->ss_size = vg_scss.altstack.ss_size;
516 oss->ss_flags = sas_ss_flags(m_esp);
517 }
518
519 if (ss != NULL) {
520 if (on_sig_stack(VG_(threads)[tid].m_esp)) {
521 SET_EAX(tid, -VKI_EPERM);
522 return;
523 }
524 if (ss->ss_flags != VKI_SS_DISABLE
525 && ss->ss_flags != VKI_SS_ONSTACK
526 && ss->ss_flags != 0) {
527 SET_EAX(tid, -VKI_EINVAL);
528 return;
529 }
530 if (ss->ss_flags == VKI_SS_DISABLE) {
531 vg_scss.altstack.ss_size = 0;
532 vg_scss.altstack.ss_sp = NULL;
533 } else {
534 if (ss->ss_size < VKI_MINSIGSTKSZ) {
535 SET_EAX(tid, -VKI_ENOMEM);
536 return;
537 }
538 }
539 vg_scss.altstack.ss_sp = ss->ss_sp;
540 vg_scss.altstack.ss_size = ss->ss_size;
541 }
542 SET_EAX(tid, 0);
543}
544
545
sewardj018f7622002-05-15 21:13:39 +0000546void VG_(do__NR_sigaction) ( ThreadId tid )
547{
548 Int signo;
549 vki_ksigaction* new_act;
550 vki_ksigaction* old_act;
551 vki_ksigset_t irrelevant_sigmask;
552
553 vg_assert(VG_(is_valid_tid)(tid));
554 signo = VG_(threads)[tid].m_ebx; /* int sigNo */
555 new_act = (vki_ksigaction*)(VG_(threads)[tid].m_ecx);
556 old_act = (vki_ksigaction*)(VG_(threads)[tid].m_edx);
557
558 if (VG_(clo_trace_signals))
559 VG_(message)(Vg_DebugExtraMsg,
560 "__NR_sigaction: tid %d, sigNo %d, "
561 "new 0x%x, old 0x%x, new flags 0x%x",
562 tid, signo, (UInt)new_act, (UInt)old_act,
563 (UInt)(new_act ? new_act->ksa_flags : 0) );
564
565 /* Rule out various error conditions. The aim is to ensure that if
566 when the call is passed to the kernel it will definitely
567 succeed. */
568
569 /* Reject out-of-range signal numbers. */
570 if (signo < 1 || signo > VKI_KNSIG) goto bad_signo;
571
572 /* Reject attempts to set a handler (or set ignore) for SIGKILL. */
573 if ( (signo == VKI_SIGKILL || signo == VKI_SIGSTOP)
574 && new_act
575 && new_act->ksa_handler != VKI_SIG_DFL)
576 goto bad_sigkill_or_sigstop;
577
578 /* If the client supplied non-NULL old_act, copy the relevant SCSS
579 entry into it. */
580 if (old_act) {
581 old_act->ksa_handler = vg_scss.scss_per_sig[signo].scss_handler;
582 old_act->ksa_flags = vg_scss.scss_per_sig[signo].scss_flags;
583 old_act->ksa_mask = vg_scss.scss_per_sig[signo].scss_mask;
584 old_act->ksa_restorer = vg_scss.scss_per_sig[signo].scss_restorer;
585 }
586
587 /* And now copy new SCSS entry from new_act. */
588 if (new_act) {
589 vg_scss.scss_per_sig[signo].scss_handler = new_act->ksa_handler;
590 vg_scss.scss_per_sig[signo].scss_flags = new_act->ksa_flags;
591 vg_scss.scss_per_sig[signo].scss_mask = new_act->ksa_mask;
592 vg_scss.scss_per_sig[signo].scss_restorer = new_act->ksa_restorer;
593 }
594
595 /* All happy bunnies ... */
596 if (new_act) {
597 VG_(block_all_host_signals)( &irrelevant_sigmask );
598 VG_(handle_SCSS_change)( False /* lazy update */ );
599 }
600 SET_EAX(tid, 0);
601 return;
602
603 bad_signo:
njn25e49d8e72002-09-23 09:36:25 +0000604 if (VG_(needs).core_errors)
605 VG_(message)(Vg_UserMsg,
606 "Warning: bad signal number %d in __NR_sigaction.",
607 signo);
sewardj018f7622002-05-15 21:13:39 +0000608 SET_EAX(tid, -VKI_EINVAL);
609 return;
610
611 bad_sigkill_or_sigstop:
njn25e49d8e72002-09-23 09:36:25 +0000612 if (VG_(needs).core_errors)
613 VG_(message)(Vg_UserMsg,
614 "Warning: attempt to set %s handler in __NR_sigaction.",
615 signo == VKI_SIGKILL ? "SIGKILL" : "SIGSTOP" );
sewardj018f7622002-05-15 21:13:39 +0000616
617 SET_EAX(tid, -VKI_EINVAL);
618 return;
619}
620
621
622static
623void do_sigprocmask_bitops ( Int vki_how,
624 vki_ksigset_t* orig_set,
625 vki_ksigset_t* modifier )
626{
627 switch (vki_how) {
628 case VKI_SIG_BLOCK:
629 VG_(ksigaddset_from_set)( orig_set, modifier );
630 break;
631 case VKI_SIG_UNBLOCK:
632 VG_(ksigdelset_from_set)( orig_set, modifier );
633 break;
634 case VKI_SIG_SETMASK:
635 *orig_set = *modifier;
636 break;
637 default:
njne427a662002-10-02 11:08:25 +0000638 VG_(core_panic)("do_sigprocmask_bitops");
sewardj018f7622002-05-15 21:13:39 +0000639 break;
640 }
641}
642
643/* Handle blocking mask set/get uniformly for threads and process as a
644 whole. If tid==VG_INVALID_THREADID, this is really
645 __NR_sigprocmask, in which case we set the masks for all threads to
646 the "set" and return in "oldset" that from the root thread (1).
647 Otherwise, tid will denote a valid thread, in which case we just
648 set/get its mask.
649
650 Note that the thread signal masks are an implicit part of SCSS,
651 which is why this routine is allowed to mess with them.
652*/
653static
654void do_setmask ( ThreadId tid,
655 Int how,
656 vki_ksigset_t* newset,
657 vki_ksigset_t* oldset )
658{
659 vki_ksigset_t irrelevant_sigmask;
660
661 if (VG_(clo_trace_signals))
sewardja464e5c2002-05-23 17:34:49 +0000662 VG_(message)(Vg_DebugExtraMsg,
sewardj3a951cf2002-05-15 22:25:47 +0000663 "do_setmask: tid = %d (%d means ALL), how = %d (%s), set = %p",
sewardj018f7622002-05-15 21:13:39 +0000664 tid,
sewardj3a951cf2002-05-15 22:25:47 +0000665 VG_INVALID_THREADID,
sewardj018f7622002-05-15 21:13:39 +0000666 how,
667 how==VKI_SIG_BLOCK ? "SIG_BLOCK" : (
668 how==VKI_SIG_UNBLOCK ? "SIG_UNBLOCK" : (
669 how==VKI_SIG_SETMASK ? "SIG_SETMASK" : "???")),
670 newset
671 );
672
673 if (tid == VG_INVALID_THREADID) {
674 /* Behave as if __NR_sigprocmask. */
675 if (oldset) {
676 /* A bit fragile. Should do better here really. */
677 vg_assert(VG_(threads)[1].status != VgTs_Empty);
678 *oldset = VG_(threads)[1].sig_mask;
679 }
680 if (newset) {
681 ThreadId tidd;
682 for (tidd = 1; tidd < VG_N_THREADS; tidd++) {
683 if (VG_(threads)[tidd].status == VgTs_Empty)
684 continue;
685 do_sigprocmask_bitops (
686 how, &VG_(threads)[tidd].sig_mask, newset );
687 }
688 }
689 } else {
690 /* Just do this thread. */
691 vg_assert(VG_(is_valid_tid)(tid));
692 if (oldset)
693 *oldset = VG_(threads)[tid].sig_mask;
694 if (newset)
695 do_sigprocmask_bitops (
696 how, &VG_(threads)[tid].sig_mask, newset );
697 }
698
699 if (newset) {
700 VG_(block_all_host_signals)( &irrelevant_sigmask );
701 VG_(handle_SCSS_change)( False /* lazy update */ );
702 }
703}
704
705
706void VG_(do__NR_sigprocmask) ( ThreadId tid,
707 Int how,
708 vki_ksigset_t* set,
709 vki_ksigset_t* oldset )
710{
711 if (how == VKI_SIG_BLOCK || how == VKI_SIG_UNBLOCK
712 || how == VKI_SIG_SETMASK) {
713 vg_assert(VG_(is_valid_tid)(tid));
714 do_setmask ( VG_INVALID_THREADID, how, set, oldset );
715 /* Syscall returns 0 (success) to its thread. */
716 SET_EAX(tid, 0);
717 } else {
718 VG_(message)(Vg_DebugMsg,
719 "sigprocmask: unknown `how' field %d", how);
720 SET_EAX(tid, -VKI_EINVAL);
721 }
722}
723
724
725void VG_(do_pthread_sigmask_SCSS_upd) ( ThreadId tid,
726 Int how,
727 vki_ksigset_t* set,
728 vki_ksigset_t* oldset )
729{
730 /* Assume that how has been validated by caller. */
731 vg_assert(how == VKI_SIG_BLOCK || how == VKI_SIG_UNBLOCK
732 || how == VKI_SIG_SETMASK);
733 vg_assert(VG_(is_valid_tid)(tid));
734 do_setmask ( tid, how, set, oldset );
735 /* The request return code is set in do_pthread_sigmask */
736}
737
738
739void VG_(send_signal_to_thread) ( ThreadId thread, Int sig )
740{
741 Int res;
742 vg_assert(VG_(is_valid_tid)(thread));
743 vg_assert(sig >= 1 && sig <= VKI_KNSIG);
744
745 switch ((UInt)(vg_scss.scss_per_sig[sig].scss_handler)) {
746
sewardjc9792e32002-05-21 00:05:10 +0000747 case ((UInt)VKI_SIG_IGN):
sewardj018f7622002-05-15 21:13:39 +0000748 if (VG_(clo_trace_signals))
749 VG_(message)(Vg_DebugMsg,
750 "send_signal %d to_thread %d: IGN, ignored", sig, thread );
751 break;
752
sewardjc9792e32002-05-21 00:05:10 +0000753 case ((UInt)VKI_SIG_DFL):
sewardj018f7622002-05-15 21:13:39 +0000754 /* This is the tricky case. Since we don't handle default
755 actions, the simple thing is to send someone round to the
756 front door and signal there. Then the kernel will do
757 whatever it does with the default action. */
sewardjdcaf3122002-09-30 23:12:33 +0000758 res = VG_(kkill)( VG_(getpid)(), sig );
sewardj018f7622002-05-15 21:13:39 +0000759 vg_assert(res == 0);
760 break;
761
762 default:
763 if (!vg_dcss.dcss_sigpending[sig]) {
764 vg_dcss.dcss_sigpending[sig] = True;
765 vg_dcss.dcss_destthread[sig] = thread;
766 if (VG_(clo_trace_signals))
767 VG_(message)(Vg_DebugMsg,
768 "send_signal %d to_thread %d: now pending", sig, thread );
769 } else {
770 if (vg_dcss.dcss_destthread[sig] == thread) {
771 if (VG_(clo_trace_signals))
772 VG_(message)(Vg_DebugMsg,
773 "send_signal %d to_thread %d: already pending ... "
774 "discarded", sig, thread );
775 } else {
776 if (VG_(clo_trace_signals))
777 VG_(message)(Vg_DebugMsg,
778 "send_signal %d to_thread %d: was pending for %d, "
779 "now pending for %d",
780 sig, thread, vg_dcss.dcss_destthread[sig], thread );
781 vg_dcss.dcss_destthread[sig] = thread;
782 }
783 }
784 }
785}
786
787
sewardjefbfcdf2002-06-19 17:35:45 +0000788/* Store in set the signals which could be delivered to this thread
789 right now (since they are pending) but cannot be, because the
790 thread has masked them out. */
791void VG_(do_sigpending) ( ThreadId tid, vki_ksigset_t* set )
792{
793 Int sig, res;
794 Bool maybe_pend;
795 vki_ksigset_t process_pending;
796
797 /* Get the set of signals which are pending for the process as a
798 whole. */
sewardjdcaf3122002-09-30 23:12:33 +0000799 res = VG_(ksigpending)( &process_pending );
sewardjefbfcdf2002-06-19 17:35:45 +0000800 vg_assert(res == 0);
801
802 VG_(ksigemptyset)(set);
803 for (sig = 1; sig <= VKI_KNSIG; sig++) {
804
805 /* Figure out if the signal could be pending for this thread.
806 There are two cases. */
807 maybe_pend = False;
808
809 /* Case 1: perhaps the signal is pending for the process as a
810 whole -- that is, is blocked even valgrind's signal
811 handler. */
812 if (VG_(ksigismember)( &process_pending, sig ))
813 maybe_pend = True;
814
815 /* Case 2: the signal has been collected by our handler and is
816 now awaiting disposition inside valgrind. */
817 if (/* is it pending at all? */
818 vg_dcss.dcss_sigpending[sig]
819 &&
820 /* check it is not specifically directed to some other thread */
821 (vg_dcss.dcss_destthread[sig] == VG_INVALID_THREADID
822 || vg_dcss.dcss_destthread[sig] == tid)
823 )
824 maybe_pend = True;
825
826 if (!maybe_pend)
827 continue; /* this signal just ain't pending! */
828
829 /* Check other necessary conditions now ... */
830
831 if (VG_(ksigismember)( &VG_(threads)[tid].sigs_waited_for, sig ))
832 continue; /* tid is sigwaiting for sig, so will never be
833 offered to a handler */
834 if (! VG_(ksigismember)( &VG_(threads)[tid].sig_mask, sig ))
835 continue; /* not blocked in this thread */
836
837 /* Ok, sig could be delivered to this thread if only it wasn't
838 masked out. So we add it to set. */
839 VG_(ksigaddset)( set, sig );
840 }
841}
842
843
sewardj018f7622002-05-15 21:13:39 +0000844/* ---------------------------------------------------------------------
845 LOW LEVEL STUFF TO DO WITH SIGNALS: IMPLEMENTATION
846 ------------------------------------------------------------------ */
sewardj77e466c2002-04-14 02:29:29 +0000847
sewardj2e93c502002-04-12 11:12:52 +0000848/* ---------------------------------------------------------------------
849 Handy utilities to block/restore all host signals.
850 ------------------------------------------------------------------ */
851
852/* Block all host signals, dumping the old mask in *saved_mask. */
853void VG_(block_all_host_signals) ( /* OUT */ vki_ksigset_t* saved_mask )
854{
855 Int ret;
856 vki_ksigset_t block_procmask;
857 VG_(ksigfillset)(&block_procmask);
858 ret = VG_(ksigprocmask)
859 (VKI_SIG_SETMASK, &block_procmask, saved_mask);
860 vg_assert(ret == 0);
861}
862
863/* Restore the blocking mask using the supplied saved one. */
sewardj018f7622002-05-15 21:13:39 +0000864void VG_(restore_all_host_signals) ( /* IN */ vki_ksigset_t* saved_mask )
sewardj2e93c502002-04-12 11:12:52 +0000865{
866 Int ret;
867 ret = VG_(ksigprocmask)(VKI_SIG_SETMASK, saved_mask, NULL);
868 vg_assert(ret == 0);
869}
sewardjde4a1d02002-03-22 01:27:54 +0000870
871
872/* ---------------------------------------------------------------------
873 The signal simulation proper. A simplified version of what the
874 Linux kernel does.
875 ------------------------------------------------------------------ */
876
877/* A structure in which to save the application's registers
878 during the execution of signal handlers. */
879
880typedef
881 struct {
sewardjf247eae2002-09-27 00:46:59 +0000882 /* These 4 are parameters to the signal handler. The order of
883 them is important, since this whole struct is pushed onto the
884 client's stack at delivery time. The first 4 words -- which
885 will be at the top of the stack -- constitute 4 arg words to
886 the handler. */
887
888 /* Sig handler's (bogus) return address */
889 Addr retaddr;
890 /* The arg to the sig handler. We need to inspect this after
891 the handler returns, but it's unreasonable to assume that the
892 handler won't change it. So we keep a second copy of it in
893 sigNo_private. */
894 Int sigNo;
895 /* ptr to siginfo_t; NULL for now. */
896 Addr psigInfo;
897 /* ptr to ucontext; NULL for now. */
898 Addr puContext;
899
900 /* The rest are private fields which the handler is unaware of. */
901
sewardj2e93c502002-04-12 11:12:52 +0000902 /* Sanity check word. */
sewardjde4a1d02002-03-22 01:27:54 +0000903 UInt magicPI;
sewardjf247eae2002-09-27 00:46:59 +0000904 /* Safely-saved version of sigNo, as described above. */
905 Int sigNo_private;
sewardj2e93c502002-04-12 11:12:52 +0000906 /* Saved processor state. */
sewardjb91ae7f2003-04-29 23:50:00 +0000907 UInt ssestate[VG_SIZE_OF_SSESTATE_W];
sewardjde4a1d02002-03-22 01:27:54 +0000908 UInt eax;
909 UInt ecx;
910 UInt edx;
911 UInt ebx;
912 UInt ebp;
913 UInt esp;
914 UInt esi;
915 UInt edi;
916 Addr eip;
917 UInt eflags;
sewardj2e93c502002-04-12 11:12:52 +0000918 /* Scheduler-private stuff: what was the thread's status prior to
919 delivering this signal? */
920 ThreadStatus status;
921 /* Sanity check word. Is the highest-addressed word; do not
922 move!*/
sewardjde4a1d02002-03-22 01:27:54 +0000923 UInt magicE;
924 }
sewardj2e93c502002-04-12 11:12:52 +0000925 VgSigFrame;
sewardjde4a1d02002-03-22 01:27:54 +0000926
927
928
sewardjde4a1d02002-03-22 01:27:54 +0000929/* Set up a stack frame (VgSigContext) for the client's signal
930 handler. This includes the signal number and a bogus return
931 address. */
932static
sewardj2e93c502002-04-12 11:12:52 +0000933void vg_push_signal_frame ( ThreadId tid, int sigNo )
sewardjde4a1d02002-03-22 01:27:54 +0000934{
935 Int i;
sewardj2342c972002-05-22 23:34:20 +0000936 Addr esp, esp_top_of_frame;
sewardj2e93c502002-04-12 11:12:52 +0000937 VgSigFrame* frame;
938 ThreadState* tst;
939
sewardj2342c972002-05-22 23:34:20 +0000940 vg_assert(sigNo >= 1 && sigNo <= VKI_KNSIG);
sewardj018f7622002-05-15 21:13:39 +0000941 vg_assert(VG_(is_valid_tid)(tid));
942 tst = & VG_(threads)[tid];
sewardj2e93c502002-04-12 11:12:52 +0000943
sewardj2342c972002-05-22 23:34:20 +0000944 if (/* this signal asked to run on an alt stack */
945 (vg_scss.scss_per_sig[sigNo].scss_flags & VKI_SA_ONSTACK)
946 && /* there is a defined and enabled alt stack, which we're not
947 already using. Logic from get_sigframe in
948 arch/i386/kernel/signal.c. */
949 sas_ss_flags(tst->m_esp) == 0
950 ) {
951 esp_top_of_frame
952 = (Addr)(vg_scss.altstack.ss_sp) + vg_scss.altstack.ss_size;
953 if (VG_(clo_trace_signals))
954 VG_(message)(Vg_DebugMsg,
955 "delivering signal %d to thread %d: on ALT STACK",
956 sigNo, tid );
njnfdc28af2003-02-24 10:36:48 +0000957
958 /* Signal delivery to skins */
959 VG_TRACK( pre_deliver_signal, tid, sigNo, /*alt_stack*/False );
960
sewardj2342c972002-05-22 23:34:20 +0000961 } else {
962 esp_top_of_frame = tst->m_esp;
njnfdc28af2003-02-24 10:36:48 +0000963
964 /* Signal delivery to skins */
965 VG_TRACK( pre_deliver_signal, tid, sigNo, /*alt_stack*/True );
sewardj2342c972002-05-22 23:34:20 +0000966 }
967
968 esp = esp_top_of_frame;
sewardj2e93c502002-04-12 11:12:52 +0000969 esp -= sizeof(VgSigFrame);
970 frame = (VgSigFrame*)esp;
njn25e49d8e72002-09-23 09:36:25 +0000971
972 /* For tracking memory events, indicate the entire frame has been
973 * allocated, but pretend that only the first four words are written */
974 VG_TRACK( new_mem_stack_signal, (Addr)frame, sizeof(VgSigFrame) );
975
sewardj2e93c502002-04-12 11:12:52 +0000976 /* Assert that the frame is placed correctly. */
977 vg_assert( (sizeof(VgSigFrame) & 0x3) == 0 );
978 vg_assert( ((Char*)(&frame->magicE)) + sizeof(UInt)
sewardj2342c972002-05-22 23:34:20 +0000979 == ((Char*)(esp_top_of_frame)) );
sewardj2e93c502002-04-12 11:12:52 +0000980
njn25e49d8e72002-09-23 09:36:25 +0000981 /* retaddr, sigNo, psigInfo, puContext fields are to be written */
982 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst, "signal handler frame",
983 (Addr)esp, 16 );
sewardj2e93c502002-04-12 11:12:52 +0000984 frame->retaddr = (UInt)(&VG_(signalreturn_bogusRA));
985 frame->sigNo = sigNo;
sewardjf247eae2002-09-27 00:46:59 +0000986 frame->sigNo_private = sigNo;
sewardj2e93c502002-04-12 11:12:52 +0000987 frame->psigInfo = (Addr)NULL;
988 frame->puContext = (Addr)NULL;
989 frame->magicPI = 0x31415927;
990
sewardjb91ae7f2003-04-29 23:50:00 +0000991 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
992 frame->ssestate[i] = tst->m_sse[i];
sewardjde4a1d02002-03-22 01:27:54 +0000993
sewardj2e93c502002-04-12 11:12:52 +0000994 frame->eax = tst->m_eax;
995 frame->ecx = tst->m_ecx;
996 frame->edx = tst->m_edx;
997 frame->ebx = tst->m_ebx;
998 frame->ebp = tst->m_ebp;
999 frame->esp = tst->m_esp;
1000 frame->esi = tst->m_esi;
1001 frame->edi = tst->m_edi;
1002 frame->eip = tst->m_eip;
1003 frame->eflags = tst->m_eflags;
sewardjde4a1d02002-03-22 01:27:54 +00001004
sewardj2e93c502002-04-12 11:12:52 +00001005 frame->status = tst->status;
sewardjde4a1d02002-03-22 01:27:54 +00001006
sewardj2e93c502002-04-12 11:12:52 +00001007 frame->magicE = 0x27182818;
1008
1009 /* Set the thread so it will next run the handler. */
1010 tst->m_esp = esp;
sewardj018f7622002-05-15 21:13:39 +00001011 tst->m_eip = (Addr)vg_scss.scss_per_sig[sigNo].scss_handler;
sewardj2e93c502002-04-12 11:12:52 +00001012 /* This thread needs to be marked runnable, but we leave that the
1013 caller to do. */
sewardjde4a1d02002-03-22 01:27:54 +00001014
njn25e49d8e72002-09-23 09:36:25 +00001015 /* retaddr, sigNo, psigInfo, puContext fields have been written --
1016 at 0(%ESP) .. 12(%ESP) */
1017 VG_TRACK( post_mem_write, (Addr)esp, 16 );
sewardjde4a1d02002-03-22 01:27:54 +00001018
sewardjde4a1d02002-03-22 01:27:54 +00001019 /*
1020 VG_(printf)("pushed signal frame; %%ESP now = %p, next %%EBP = %p\n",
sewardj2e93c502002-04-12 11:12:52 +00001021 esp, tst->m_eip);
sewardjde4a1d02002-03-22 01:27:54 +00001022 */
1023}
1024
1025
1026/* Clear the signal frame created by vg_push_signal_frame, restore the
1027 simulated machine state, and return the signal number that the
1028 frame was for. */
1029static
sewardj2e93c502002-04-12 11:12:52 +00001030Int vg_pop_signal_frame ( ThreadId tid )
sewardjde4a1d02002-03-22 01:27:54 +00001031{
sewardj2e93c502002-04-12 11:12:52 +00001032 Addr esp;
sewardjde4a1d02002-03-22 01:27:54 +00001033 Int sigNo, i;
sewardj2e93c502002-04-12 11:12:52 +00001034 VgSigFrame* frame;
1035 ThreadState* tst;
sewardjde4a1d02002-03-22 01:27:54 +00001036
sewardj018f7622002-05-15 21:13:39 +00001037 vg_assert(VG_(is_valid_tid)(tid));
1038 tst = & VG_(threads)[tid];
sewardj2e93c502002-04-12 11:12:52 +00001039
sewardj54cacf02002-04-12 23:24:59 +00001040 /* Correctly reestablish the frame base address. */
sewardj2e93c502002-04-12 11:12:52 +00001041 esp = tst->m_esp;
sewardj54cacf02002-04-12 23:24:59 +00001042 frame = (VgSigFrame*)
1043 (esp -4 /* because the handler's RET pops the RA */
1044 +20 /* because signalreturn_bogusRA pushes 5 words */);
sewardj2e93c502002-04-12 11:12:52 +00001045
1046 vg_assert(frame->magicPI == 0x31415927);
1047 vg_assert(frame->magicE == 0x27182818);
sewardjde4a1d02002-03-22 01:27:54 +00001048 if (VG_(clo_trace_signals))
sewardjb48e5002002-05-13 00:16:03 +00001049 VG_(message)(Vg_DebugMsg,
1050 "vg_pop_signal_frame (thread %d): valid magic", tid);
sewardjde4a1d02002-03-22 01:27:54 +00001051
1052 /* restore machine state */
sewardjb91ae7f2003-04-29 23:50:00 +00001053 for (i = 0; i < VG_SIZE_OF_SSESTATE_W; i++)
1054 tst->m_sse[i] = frame->ssestate[i];
sewardjde4a1d02002-03-22 01:27:54 +00001055
sewardj2342c972002-05-22 23:34:20 +00001056 /* Mark the frame structure as nonaccessible. */
njn25e49d8e72002-09-23 09:36:25 +00001057 VG_TRACK( die_mem_stack_signal, (Addr)frame, sizeof(VgSigFrame) );
sewardjde4a1d02002-03-22 01:27:54 +00001058
1059 /* Restore machine state from the saved context. */
sewardj2e93c502002-04-12 11:12:52 +00001060 tst->m_eax = frame->eax;
1061 tst->m_ecx = frame->ecx;
1062 tst->m_edx = frame->edx;
1063 tst->m_ebx = frame->ebx;
1064 tst->m_ebp = frame->ebp;
1065 tst->m_esp = frame->esp;
1066 tst->m_esi = frame->esi;
1067 tst->m_edi = frame->edi;
1068 tst->m_eflags = frame->eflags;
1069 tst->m_eip = frame->eip;
sewardjf247eae2002-09-27 00:46:59 +00001070
1071 /* don't use the copy exposed to the handler; it might have changed
1072 it. */
1073 sigNo = frame->sigNo_private;
sewardj2e93c502002-04-12 11:12:52 +00001074
1075 /* And restore the thread's status to what it was before the signal
1076 was delivered. */
1077 tst->status = frame->status;
1078
njnfdc28af2003-02-24 10:36:48 +00001079 /* Notify skins */
1080 VG_TRACK( post_deliver_signal, tid, sigNo );
1081
sewardjde4a1d02002-03-22 01:27:54 +00001082 return sigNo;
1083}
1084
1085
1086/* A handler is returning. Restore the machine state from the stacked
1087 VgSigContext and continue with whatever was going on before the
sewardj77e466c2002-04-14 02:29:29 +00001088 handler ran. Returns the SA_RESTART syscall-restartability-status
1089 of the delivered signal. */
sewardjde4a1d02002-03-22 01:27:54 +00001090
sewardj77e466c2002-04-14 02:29:29 +00001091Bool VG_(signal_returns) ( ThreadId tid )
sewardjde4a1d02002-03-22 01:27:54 +00001092{
sewardj2e93c502002-04-12 11:12:52 +00001093 Int sigNo;
sewardjde4a1d02002-03-22 01:27:54 +00001094 vki_ksigset_t saved_procmask;
1095
1096 /* Block host signals ... */
sewardj2e93c502002-04-12 11:12:52 +00001097 VG_(block_all_host_signals)( &saved_procmask );
sewardjde4a1d02002-03-22 01:27:54 +00001098
sewardj2e93c502002-04-12 11:12:52 +00001099 /* Pop the signal frame and restore tid's status to what it was
1100 before the signal was delivered. */
1101 sigNo = vg_pop_signal_frame(tid);
sewardjde4a1d02002-03-22 01:27:54 +00001102
sewardjb48e5002002-05-13 00:16:03 +00001103 vg_assert(sigNo >= 1 && sigNo <= VKI_KNSIG);
sewardjde4a1d02002-03-22 01:27:54 +00001104
1105 /* Unlock and return. */
sewardj018f7622002-05-15 21:13:39 +00001106 VG_(restore_all_host_signals)( &saved_procmask );
sewardjde4a1d02002-03-22 01:27:54 +00001107
sewardj77e466c2002-04-14 02:29:29 +00001108 /* Scheduler now can resume this thread, or perhaps some other.
1109 Tell the scheduler whether or not any syscall interrupted by
1110 this signal should be restarted, if possible, or no. */
sewardj018f7622002-05-15 21:13:39 +00001111 return
1112 (vg_scss.scss_per_sig[sigNo].scss_flags & VKI_SA_RESTART)
1113 ? True
1114 : False;
sewardjde4a1d02002-03-22 01:27:54 +00001115}
1116
1117
1118/* Deliver all pending signals, by building stack frames for their
sewardj14e03422002-04-24 19:51:31 +00001119 handlers. Return True if any signals were delivered. */
sewardjb48e5002002-05-13 00:16:03 +00001120Bool VG_(deliver_signals) ( void )
sewardjde4a1d02002-03-22 01:27:54 +00001121{
sewardjde4a1d02002-03-22 01:27:54 +00001122 vki_ksigset_t saved_procmask;
sewardj2e93c502002-04-12 11:12:52 +00001123 Int sigNo;
sewardj018f7622002-05-15 21:13:39 +00001124 Bool found, scss_changed;
sewardjb48e5002002-05-13 00:16:03 +00001125 ThreadState* tst;
1126 ThreadId tid;
1127
sewardj018f7622002-05-15 21:13:39 +00001128 /* A cheap check. We don't need to have exclusive access to the
1129 pending array, because in the worst case, vg_oursignalhandler
1130 will add signals, causing us to return, thinking there are no
1131 signals to deliver, when in fact there are some. A subsequent
1132 call here will handle the signal(s) we missed. */
sewardjde4a1d02002-03-22 01:27:54 +00001133 found = False;
sewardjb48e5002002-05-13 00:16:03 +00001134 for (sigNo = 1; sigNo <= VKI_KNSIG; sigNo++)
sewardj018f7622002-05-15 21:13:39 +00001135 if (vg_dcss.dcss_sigpending[sigNo])
sewardjb48e5002002-05-13 00:16:03 +00001136 found = True;
sewardjde4a1d02002-03-22 01:27:54 +00001137
sewardj14e03422002-04-24 19:51:31 +00001138 if (!found) return False;
sewardjde4a1d02002-03-22 01:27:54 +00001139
1140 /* Now we have to do it properly. Get exclusive access by
1141 blocking all the host's signals. That means vg_oursignalhandler
1142 can't run whilst we are messing with stuff.
1143 */
sewardj018f7622002-05-15 21:13:39 +00001144 scss_changed = False;
sewardj2e93c502002-04-12 11:12:52 +00001145 VG_(block_all_host_signals)( &saved_procmask );
sewardjde4a1d02002-03-22 01:27:54 +00001146
sewardj2e93c502002-04-12 11:12:52 +00001147 /* Look for signals to deliver ... */
sewardjb48e5002002-05-13 00:16:03 +00001148 for (sigNo = 1; sigNo <= VKI_KNSIG; sigNo++) {
sewardj018f7622002-05-15 21:13:39 +00001149
1150 if (!vg_dcss.dcss_sigpending[sigNo])
1151 continue;
1152
sewardjb48e5002002-05-13 00:16:03 +00001153 /* sigNo is pending. Try to find a suitable thread to deliver
1154 it to. */
sewardjb48e5002002-05-13 00:16:03 +00001155 /* First off, are any threads in sigwait() for the signal?
1156 If so just give to one of them and have done. */
1157 for (tid = 1; tid < VG_N_THREADS; tid++) {
sewardj018f7622002-05-15 21:13:39 +00001158 tst = & VG_(threads)[tid];
sewardj0e357db2002-06-04 09:44:09 +00001159 /* Is tid waiting for a signal? If not, ignore. */
sewardjb48e5002002-05-13 00:16:03 +00001160 if (tst->status != VgTs_WaitSIG)
1161 continue;
sewardjb83b6a72002-06-04 10:34:40 +00001162 /* Is the signal directed at a specific thread other than
sewardj0e357db2002-06-04 09:44:09 +00001163 this one? If yes, ignore. */
1164 if (vg_dcss.dcss_destthread[sigNo] != VG_INVALID_THREADID
1165 && vg_dcss.dcss_destthread[sigNo] != tid)
1166 continue;
1167 /* Is tid waiting for the signal? If not, ignore. */
sewardjb48e5002002-05-13 00:16:03 +00001168 if (VG_(ksigismember)(&(tst->sigs_waited_for), sigNo))
1169 break;
1170 }
1171 if (tid < VG_N_THREADS) {
1172 UInt* sigwait_args;
sewardj018f7622002-05-15 21:13:39 +00001173 tst = & VG_(threads)[tid];
sewardjb48e5002002-05-13 00:16:03 +00001174 if (VG_(clo_trace_signals) || VG_(clo_trace_sched))
1175 VG_(message)(Vg_DebugMsg,
1176 "releasing thread %d from sigwait() due to signal %d",
1177 tid, sigNo );
1178 sigwait_args = (UInt*)(tst->m_eax);
1179 if (NULL != (UInt*)(sigwait_args[2])) {
1180 *(Int*)(sigwait_args[2]) = sigNo;
njn25e49d8e72002-09-23 09:36:25 +00001181 VG_TRACK( post_mem_write, (Addr)sigwait_args[2], sizeof(UInt));
sewardjb48e5002002-05-13 00:16:03 +00001182 }
sewardj018f7622002-05-15 21:13:39 +00001183 SET_EDX(tid, 0);
sewardjb48e5002002-05-13 00:16:03 +00001184 tst->status = VgTs_Runnable;
sewardj811d1412002-05-13 00:38:52 +00001185 VG_(ksigemptyset)(&tst->sigs_waited_for);
sewardj018f7622002-05-15 21:13:39 +00001186 scss_changed = True;
1187 vg_dcss.dcss_sigpending[sigNo] = False;
1188 vg_dcss.dcss_destthread[sigNo] = VG_INVALID_THREADID;
1189 /*paranoia*/
sewardjb48e5002002-05-13 00:16:03 +00001190 continue; /* for (sigNo = 1; ...) loop */
1191 }
1192
1193 /* Well, nobody appears to be sigwaiting for it. So we really
sewardj018f7622002-05-15 21:13:39 +00001194 are delivering the signal in the usual way. And that the
1195 client really has a handler for this thread! */
1196 vg_assert(vg_dcss.dcss_sigpending[sigNo]);
sewardj088f1182002-06-13 17:47:05 +00001197
1198 /* A recent addition, so as to stop seriously wierd progs dying
1199 at the following assertion (which this renders redundant,
1200 btw). */
1201 if (vg_scss.scss_per_sig[sigNo].scss_handler == VKI_SIG_IGN
1202 || vg_scss.scss_per_sig[sigNo].scss_handler == VKI_SIG_DFL) {
1203 /* Strange; perhaps the handler disappeared before we could
1204 deliver the signal. */
1205 VG_(message)(Vg_DebugMsg,
1206 "discarding signal %d for thread %d because handler missing",
1207 sigNo, tid );
1208 vg_dcss.dcss_sigpending[sigNo] = False;
1209 vg_dcss.dcss_destthread[sigNo] = VG_INVALID_THREADID;
1210 continue; /* for (sigNo = 1; ...) loop */
1211 }
1212
sewardj018f7622002-05-15 21:13:39 +00001213 vg_assert(vg_scss.scss_per_sig[sigNo].scss_handler != VKI_SIG_IGN
1214 && vg_scss.scss_per_sig[sigNo].scss_handler != VKI_SIG_DFL);
sewardjb48e5002002-05-13 00:16:03 +00001215
sewardj018f7622002-05-15 21:13:39 +00001216 tid = vg_dcss.dcss_destthread[sigNo];
sewardjb48e5002002-05-13 00:16:03 +00001217 vg_assert(tid == VG_INVALID_THREADID
1218 || VG_(is_valid_tid)(tid));
1219
1220 if (tid != VG_INVALID_THREADID) {
1221 /* directed to a specific thread; ensure it actually still
1222 exists ... */
sewardj018f7622002-05-15 21:13:39 +00001223 tst = & VG_(threads)[tid];
sewardjb48e5002002-05-13 00:16:03 +00001224 if (tst->status == VgTs_Empty) {
1225 /* dead, for whatever reason; ignore this signal */
1226 if (VG_(clo_trace_signals))
1227 VG_(message)(Vg_DebugMsg,
1228 "discarding signal %d for nonexistent thread %d",
1229 sigNo, tid );
sewardj018f7622002-05-15 21:13:39 +00001230 vg_dcss.dcss_sigpending[sigNo] = False;
1231 vg_dcss.dcss_destthread[sigNo] = VG_INVALID_THREADID;
sewardjb48e5002002-05-13 00:16:03 +00001232 continue; /* for (sigNo = 1; ...) loop */
njn25e49d8e72002-09-23 09:36:25 +00001233 } else if (VG_(ksigismember)(&(tst->sig_mask), sigNo)) {
1234 /* signal blocked in specific thread, so we can't
1235 deliver it just now */
1236 continue; /* for (sigNo = 1; ...) loop */
1237 }
sewardjb48e5002002-05-13 00:16:03 +00001238 } else {
1239 /* not directed to a specific thread, so search for a
1240 suitable candidate */
1241 for (tid = 1; tid < VG_N_THREADS; tid++) {
sewardj018f7622002-05-15 21:13:39 +00001242 tst = & VG_(threads)[tid];
sewardjb48e5002002-05-13 00:16:03 +00001243 if (tst->status != VgTs_Empty
1244 && !VG_(ksigismember)(&(tst->sig_mask), sigNo))
1245 break;
1246 }
1247 if (tid == VG_N_THREADS)
1248 /* All threads have this signal blocked, so we can't
1249 deliver it just now */
1250 continue; /* for (sigNo = 1; ...) loop */
1251 }
1252
1253 /* Ok, we can deliver signal sigNo to thread tid. */
sewardjde4a1d02002-03-22 01:27:54 +00001254
1255 if (VG_(clo_trace_signals))
sewardjb48e5002002-05-13 00:16:03 +00001256 VG_(message)(Vg_DebugMsg,"delivering signal %d to thread %d",
1257 sigNo, tid );
sewardjde4a1d02002-03-22 01:27:54 +00001258
1259 /* Create a signal delivery frame, and set the client's %ESP and
1260 %EIP so that when execution continues, we will enter the
1261 signal handler with the frame on top of the client's stack,
1262 as it expects. */
sewardjb48e5002002-05-13 00:16:03 +00001263 vg_assert(VG_(is_valid_tid)(tid));
sewardj2e93c502002-04-12 11:12:52 +00001264 vg_push_signal_frame ( tid, sigNo );
sewardj018f7622002-05-15 21:13:39 +00001265 VG_(threads)[tid].status = VgTs_Runnable;
sewardj2e93c502002-04-12 11:12:52 +00001266
sewardjde4a1d02002-03-22 01:27:54 +00001267 /* Signify that the signal has been delivered. */
sewardj018f7622002-05-15 21:13:39 +00001268 vg_dcss.dcss_sigpending[sigNo] = False;
1269 vg_dcss.dcss_destthread[sigNo] = VG_INVALID_THREADID;
1270
1271 if (vg_scss.scss_per_sig[sigNo].scss_flags & VKI_SA_ONESHOT) {
1272 /* Do the ONESHOT thing. */
1273 vg_scss.scss_per_sig[sigNo].scss_handler = VKI_SIG_DFL;
1274 scss_changed = True;
1275 }
sewardjde4a1d02002-03-22 01:27:54 +00001276 }
1277
1278 /* Unlock and return. */
sewardj018f7622002-05-15 21:13:39 +00001279 if (scss_changed) {
1280 /* handle_SCSS_change computes a new kernel blocking mask and
1281 applies that. */
1282 VG_(handle_SCSS_change)( False /* lazy update */ );
1283 } else {
1284 /* No SCSS change, so just restore the existing blocking
1285 mask. */
1286 VG_(restore_all_host_signals)( &saved_procmask );
sewardjb48e5002002-05-13 00:16:03 +00001287 }
sewardj018f7622002-05-15 21:13:39 +00001288
1289 return True;
sewardjb48e5002002-05-13 00:16:03 +00001290}
1291
1292
sewardjde4a1d02002-03-22 01:27:54 +00001293/* Receive a signal from the host, and either discard it or park it in
1294 the queue of pending signals. All other signals will be blocked
1295 when this handler runs. Runs with all host signals blocked, so as
1296 to have mutual exclusion when adding stuff to the queue. */
1297
sewardjb48e5002002-05-13 00:16:03 +00001298static
sewardj018f7622002-05-15 21:13:39 +00001299void vg_oursignalhandler ( Int sigNo )
sewardjde4a1d02002-03-22 01:27:54 +00001300{
sewardj872051c2002-07-13 12:12:56 +00001301 static UInt segv_warns = 0;
sewardj018f7622002-05-15 21:13:39 +00001302 ThreadId tid;
sewardj2e93c502002-04-12 11:12:52 +00001303 Int dummy_local;
sewardj018f7622002-05-15 21:13:39 +00001304 Bool sane;
sewardjde4a1d02002-03-22 01:27:54 +00001305 vki_ksigset_t saved_procmask;
1306
sewardj7a61d912002-04-25 01:27:35 +00001307 /*
1308 if (sigNo == VKI_SIGUSR1) {
1309 VG_(printf)("YOWZA! SIGUSR1\n\n");
1310 VG_(clo_trace_pthread_level) = 2;
1311 VG_(clo_trace_sched) = True;
1312 VG_(clo_trace_syscalls) = True;
1313 VG_(clo_trace_signals) = True;
1314 return;
1315 }
1316 */
1317
sewardjde4a1d02002-03-22 01:27:54 +00001318 if (VG_(clo_trace_signals)) {
1319 VG_(start_msg)(Vg_DebugMsg);
1320 VG_(add_to_msg)("signal %d arrived ... ", sigNo );
1321 }
sewardjb48e5002002-05-13 00:16:03 +00001322 vg_assert(sigNo >= 1 && sigNo <= VKI_KNSIG);
sewardjde4a1d02002-03-22 01:27:54 +00001323
1324 /* Sanity check. Ensure we're really running on the signal stack
1325 we asked for. */
1326 if ( !(
njn12a57142003-04-30 20:49:10 +00001327 ((Char*)(&(VG_(sigstack)[0])) <= (Char*)(&dummy_local))
1328 &&
1329 ((Char*)(&dummy_local) < (Char*)(&(VG_(sigstack)[VG_SIGSTACK_SIZE])))
sewardjde4a1d02002-03-22 01:27:54 +00001330 )
1331 ) {
sewardj2e93c502002-04-12 11:12:52 +00001332 VG_(message)(Vg_DebugMsg,
1333 "FATAL: signal delivered on the wrong stack?!");
1334 VG_(message)(Vg_DebugMsg,
1335 "A possible workaround follows. Please tell me");
1336 VG_(message)(Vg_DebugMsg,
1337 "(jseward@acm.org) if the suggested workaround doesn't help.");
sewardjde4a1d02002-03-22 01:27:54 +00001338 VG_(unimplemented)
sewardj2e93c502002-04-12 11:12:52 +00001339 ("support for progs compiled with -p/-pg; "
1340 "rebuild your prog without -p/-pg");
sewardjde4a1d02002-03-22 01:27:54 +00001341 }
1342
sewardj2e93c502002-04-12 11:12:52 +00001343 vg_assert((Char*)(&(VG_(sigstack)[0])) <= (Char*)(&dummy_local));
njn12a57142003-04-30 20:49:10 +00001344 vg_assert((Char*)(&dummy_local) < (Char*)(&(VG_(sigstack)[VG_SIGSTACK_SIZE])));
sewardjde4a1d02002-03-22 01:27:54 +00001345
sewardj2e93c502002-04-12 11:12:52 +00001346 VG_(block_all_host_signals)( &saved_procmask );
sewardjde4a1d02002-03-22 01:27:54 +00001347
sewardj018f7622002-05-15 21:13:39 +00001348 /* This is a sanity check. Either a signal has arrived because the
1349 client set a handler for it, or because some thread sigwaited on
1350 it. Establish that at least one of these is the case. */
1351 sane = False;
1352 if (vg_scss.scss_per_sig[sigNo].scss_handler != VKI_SIG_DFL
1353 && vg_scss.scss_per_sig[sigNo].scss_handler != VKI_SIG_IGN) {
1354 sane = True;
1355 } else {
1356 for (tid = 1; tid < VG_N_THREADS; tid++) {
1357 if (VG_(threads)[tid].status != VgTs_WaitSIG)
1358 continue;
1359 if (VG_(ksigismember)(&VG_(threads)[tid].sigs_waited_for, sigNo))
1360 sane = True;
1361 }
1362 }
1363 if (!sane) {
sewardjde4a1d02002-03-22 01:27:54 +00001364 if (VG_(clo_trace_signals)) {
1365 VG_(add_to_msg)("unexpected!");
1366 VG_(end_msg)();
1367 }
sewardj2e93c502002-04-12 11:12:52 +00001368 /* Note: we panic with all signals blocked here. Don't think
1369 that matters. */
njne427a662002-10-02 11:08:25 +00001370 VG_(core_panic)("vg_oursignalhandler: unexpected signal");
sewardjde4a1d02002-03-22 01:27:54 +00001371 }
sewardj018f7622002-05-15 21:13:39 +00001372 /* End of the sanity check. */
sewardjde4a1d02002-03-22 01:27:54 +00001373
1374 /* Decide what to do with it. */
sewardj018f7622002-05-15 21:13:39 +00001375 if (vg_dcss.dcss_sigpending[sigNo]) {
1376 /* pending; ignore it. */
sewardjde4a1d02002-03-22 01:27:54 +00001377 if (VG_(clo_trace_signals)) {
1378 VG_(add_to_msg)("already pending; discarded" );
1379 VG_(end_msg)();
1380 }
sewardj018f7622002-05-15 21:13:39 +00001381 } else {
sewardj2e93c502002-04-12 11:12:52 +00001382 /* Ok, we'd better deliver it to the client. */
sewardj2e93c502002-04-12 11:12:52 +00001383 /* Queue it up for delivery at some point in the future. */
sewardj018f7622002-05-15 21:13:39 +00001384 vg_dcss.dcss_sigpending[sigNo] = True;
1385 vg_dcss.dcss_destthread[sigNo] = VG_INVALID_THREADID;
sewardj2e93c502002-04-12 11:12:52 +00001386 if (VG_(clo_trace_signals)) {
1387 VG_(add_to_msg)("queued" );
1388 VG_(end_msg)();
sewardjde4a1d02002-03-22 01:27:54 +00001389 }
1390 }
1391
sewardj2e93c502002-04-12 11:12:52 +00001392 /* We've finished messing with the queue, so re-enable host
1393 signals. */
sewardj018f7622002-05-15 21:13:39 +00001394 VG_(restore_all_host_signals)( &saved_procmask );
sewardjde4a1d02002-03-22 01:27:54 +00001395
sewardj872051c2002-07-13 12:12:56 +00001396 if ( (sigNo == VKI_SIGSEGV || sigNo == VKI_SIGBUS
1397 || sigNo == VKI_SIGFPE || sigNo == VKI_SIGILL)
1398 &&
1399 VG_(scheduler_jmpbuf_valid)
1400 ) {
sewardj2e93c502002-04-12 11:12:52 +00001401 /* Can't continue; must longjmp back to the scheduler and thus
1402 enter the sighandler immediately. */
sewardjde4a1d02002-03-22 01:27:54 +00001403 VG_(longjmpd_on_signal) = sigNo;
sewardj2e93c502002-04-12 11:12:52 +00001404 __builtin_longjmp(VG_(scheduler_jmpbuf),1);
sewardjde4a1d02002-03-22 01:27:54 +00001405 }
sewardj872051c2002-07-13 12:12:56 +00001406
1407 if (sigNo == VKI_SIGSEGV && !VG_(scheduler_jmpbuf_valid)) {
1408 if (++segv_warns <= 3) {
1409 VG_(message)(Vg_UserMsg,
1410 "Warning: SIGSEGV not in user code; either from syscall kill()" );
1411 VG_(message)(Vg_UserMsg,
1412 " or possible Valgrind bug. "
1413 "This message is only shown 3 times." );
1414 }
1415 }
sewardjde4a1d02002-03-22 01:27:54 +00001416}
1417
1418
1419/* The outer insn loop calls here to reenable a host signal if
1420 vg_oursighandler longjmp'd.
1421*/
1422void VG_(unblock_host_signal) ( Int sigNo )
1423{
1424 Int ret;
1425 vki_ksigset_t set;
1426 VG_(ksigemptyset)(&set);
1427 ret = VG_(ksigaddset)(&set,sigNo);
1428 vg_assert(ret == 0);
1429 ret = VG_(ksigprocmask)(VKI_SIG_UNBLOCK,&set,NULL);
1430 vg_assert(ret == 0);
1431}
1432
1433
1434static __attribute((unused))
1435void pp_vg_ksigaction ( vki_ksigaction* sa )
1436{
1437 Int i;
1438 VG_(printf)("vg_ksigaction: handler %p, flags 0x%x, restorer %p\n",
sewardj9a199dc2002-04-14 13:01:38 +00001439 sa->ksa_handler, (UInt)sa->ksa_flags, sa->ksa_restorer);
sewardjde4a1d02002-03-22 01:27:54 +00001440 VG_(printf)("vg_ksigaction: { ");
sewardjb48e5002002-05-13 00:16:03 +00001441 for (i = 1; i <= VKI_KNSIG; i++)
sewardjde4a1d02002-03-22 01:27:54 +00001442 if (VG_(ksigismember(&(sa->ksa_mask),i)))
1443 VG_(printf)("%d ", i);
1444 VG_(printf)("}\n");
1445}
1446
1447
sewardj018f7622002-05-15 21:13:39 +00001448/* At startup, copy the process' real signal state to the SCSS.
1449 Whilst doing this, block all real signals. Then calculate SKSS and
1450 set the kernel to that. Also initialise DCSS.
sewardjde4a1d02002-03-22 01:27:54 +00001451*/
1452void VG_(sigstartup_actions) ( void )
1453{
1454 Int i, ret;
1455
sewardjde4a1d02002-03-22 01:27:54 +00001456 vki_ksigset_t saved_procmask;
1457 vki_kstack_t altstack_info;
1458 vki_ksigaction sa;
1459
sewardj2e93c502002-04-12 11:12:52 +00001460 /* VG_(printf)("SIGSTARTUP\n"); */
sewardjde4a1d02002-03-22 01:27:54 +00001461 /* Block all signals.
1462 saved_procmask remembers the previous mask. */
sewardj2e93c502002-04-12 11:12:52 +00001463 VG_(block_all_host_signals)( &saved_procmask );
sewardjde4a1d02002-03-22 01:27:54 +00001464
sewardj018f7622002-05-15 21:13:39 +00001465 /* Copy per-signal settings to SCSS. */
1466 for (i = 1; i <= VKI_KNSIG; i++) {
1467
1468 /* Get the old host action */
1469 ret = VG_(ksigaction)(i, NULL, &sa);
1470 vg_assert(ret == 0);
1471
1472 if (VG_(clo_trace_signals))
1473 VG_(printf)("snaffling handler 0x%x for signal %d\n",
1474 (Addr)(sa.ksa_handler), i );
1475
1476 vg_scss.scss_per_sig[i].scss_handler = sa.ksa_handler;
1477 vg_scss.scss_per_sig[i].scss_flags = sa.ksa_flags;
1478 vg_scss.scss_per_sig[i].scss_mask = sa.ksa_mask;
1479 vg_scss.scss_per_sig[i].scss_restorer = sa.ksa_restorer;
1480 }
1481
sewardj2342c972002-05-22 23:34:20 +00001482 /* Copy the alt stack, if any. */
1483 ret = VG_(ksigaltstack)(NULL, &vg_scss.altstack);
1484 vg_assert(ret == 0);
1485
sewardj018f7622002-05-15 21:13:39 +00001486 /* Copy the process' signal mask into the root thread. */
1487 vg_assert(VG_(threads)[1].status == VgTs_Runnable);
1488 VG_(threads)[1].sig_mask = saved_procmask;
1489
1490 /* Initialise DCSS. */
1491 for (i = 1; i <= VKI_KNSIG; i++) {
1492 vg_dcss.dcss_sigpending[i] = False;
1493 vg_dcss.dcss_destthread[i] = VG_INVALID_THREADID;
1494 }
1495
njn12a57142003-04-30 20:49:10 +00001496 /* Register an alternative stack for our own signal handler to run on. */
sewardjde4a1d02002-03-22 01:27:54 +00001497 altstack_info.ss_sp = &(VG_(sigstack)[0]);
njn12a57142003-04-30 20:49:10 +00001498 altstack_info.ss_size = VG_SIGSTACK_SIZE * sizeof(UInt);
sewardjde4a1d02002-03-22 01:27:54 +00001499 altstack_info.ss_flags = 0;
1500 ret = VG_(ksigaltstack)(&altstack_info, NULL);
1501 if (ret != 0) {
njne427a662002-10-02 11:08:25 +00001502 VG_(core_panic)(
sewardjde4a1d02002-03-22 01:27:54 +00001503 "vg_sigstartup_actions: couldn't install alternative sigstack");
1504 }
1505 if (VG_(clo_trace_signals)) {
1506 VG_(message)(Vg_DebugExtraMsg,
1507 "vg_sigstartup_actions: sigstack installed ok");
1508 }
1509
sewardj7a61d912002-04-25 01:27:35 +00001510 /* DEBUGGING HACK */
1511 /* VG_(ksignal)(VKI_SIGUSR1, &VG_(oursignalhandler)); */
1512
sewardj018f7622002-05-15 21:13:39 +00001513 /* Calculate SKSS and apply it. This also sets the initial kernel
1514 mask we need to run with. */
1515 VG_(handle_SCSS_change)( True /* forced update */ );
sewardjde4a1d02002-03-22 01:27:54 +00001516}
1517
1518
1519/* Copy the process' sim signal state to the real state,
1520 for when we transfer from the simulated to real CPU.
1521 PROBLEM: what if we're running a signal handler when we
1522 get here? Hmm.
1523 I guess we wind up in vg_signalreturn_bogusRA, *or* the
1524 handler has done/will do a longjmp, in which case we're ok.
1525
1526 It is important (see vg_startup.S) that this proc does not
1527 change the state of the real FPU, since it is called when
1528 running the program on the real CPU.
1529*/
1530void VG_(sigshutdown_actions) ( void )
1531{
1532 Int i, ret;
1533
sewardjde4a1d02002-03-22 01:27:54 +00001534 vki_ksigset_t saved_procmask;
1535 vki_ksigaction sa;
1536
sewardj2e93c502002-04-12 11:12:52 +00001537 VG_(block_all_host_signals)( &saved_procmask );
sewardjde4a1d02002-03-22 01:27:54 +00001538
sewardj018f7622002-05-15 21:13:39 +00001539 /* Copy per-signal settings from SCSS. */
sewardjb48e5002002-05-13 00:16:03 +00001540 for (i = 1; i <= VKI_KNSIG; i++) {
sewardj018f7622002-05-15 21:13:39 +00001541
1542 sa.ksa_handler = vg_scss.scss_per_sig[i].scss_handler;
1543 sa.ksa_flags = vg_scss.scss_per_sig[i].scss_flags;
1544 sa.ksa_mask = vg_scss.scss_per_sig[i].scss_mask;
1545 sa.ksa_restorer = vg_scss.scss_per_sig[i].scss_restorer;
1546
1547 if (VG_(clo_trace_signals))
1548 VG_(printf)("restoring handler 0x%x for signal %d\n",
1549 (Addr)(sa.ksa_handler), i );
1550
sewardje8fb72e2002-06-28 02:08:28 +00001551 /* Set the old host action */
sewardj018f7622002-05-15 21:13:39 +00001552 ret = VG_(ksigaction)(i, &sa, NULL);
sewardje8fb72e2002-06-28 02:08:28 +00001553 if (i != VKI_SIGKILL && i != VKI_SIGSTOP)
1554 vg_assert(ret == 0);
sewardjde4a1d02002-03-22 01:27:54 +00001555 }
1556
sewardj2342c972002-05-22 23:34:20 +00001557 /* Restore the sig alt stack. */
1558 ret = VG_(ksigaltstack)(&vg_scss.altstack, NULL);
1559 vg_assert(ret == 0);
1560
sewardj018f7622002-05-15 21:13:39 +00001561 /* A bit of a kludge -- set the sigmask to that of the root
1562 thread. */
1563 vg_assert(VG_(threads)[1].status != VgTs_Empty);
1564 VG_(restore_all_host_signals)( &VG_(threads)[1].sig_mask );
sewardjde4a1d02002-03-22 01:27:54 +00001565}
1566
1567
sewardjde4a1d02002-03-22 01:27:54 +00001568/*--------------------------------------------------------------------*/
1569/*--- end vg_signals.c ---*/
1570/*--------------------------------------------------------------------*/