blob: e12c7ddebfad959d9c0a751f17e4f21b522910b3 [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
11 Copyright (C) 2000-2002 Julian Seward
12 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"
sewardj54cacf02002-04-12 23:24:59 +000035#include "valgrind.h" /* for VALGRIND_MAGIC_SEQUENCE */
sewardjde4a1d02002-03-22 01:27:54 +000036
sewardj018f7622002-05-15 21:13:39 +000037/* Define to give more sanity checking for signals. */
38#define DEBUG_SIGNALS
39
40
sewardjfa356512002-05-24 00:00:59 +000041/* KNOWN BUGS 24 May 02:
42
43 - A signal is not masked in its own handler. Neither are the
44 signals in the signal's blocking mask.
45
46 - There is only one pending set for the entire process, whereas
47 POSIX seems to require each thread have its own pending set.
48 This means that a signal can only be pending for one thread at
49 a time.
50
51 - The following causes an infinite loop: start Hugs, Feb 2001
52 version, and do Control-C at the prompt. There is an infinite
53 series of sigints delivered (to the client); but also seemingly
54 to valgrind, which is very strange. I don't know why.
55
56 Probably a lot more bugs which I haven't discovered yet.
57*/
58
59
sewardj018f7622002-05-15 21:13:39 +000060/* ---------------------------------------------------------------------
61 Forwards decls.
62 ------------------------------------------------------------------ */
63
64static void vg_oursignalhandler ( Int sigNo );
65
66
67/* ---------------------------------------------------------------------
68 HIGH LEVEL STUFF TO DO WITH SIGNALS: POLICY (MOSTLY)
69 ------------------------------------------------------------------ */
70
sewardjde4a1d02002-03-22 01:27:54 +000071/* ---------------------------------------------------------------------
sewardjde4a1d02002-03-22 01:27:54 +000072 Signal state for this process.
73 ------------------------------------------------------------------ */
74
sewardj018f7622002-05-15 21:13:39 +000075
sewardjb48e5002002-05-13 00:16:03 +000076/* Base-ment of these arrays[VKI_KNSIG].
77
78 Valid signal numbers are 1 .. VKI_KNSIG inclusive.
79 Rather than subtracting 1 for indexing these arrays, which
80 is tedious and error-prone, they are simply dimensioned 1 larger,
81 and entry [0] is not used.
82 */
83
sewardjb48e5002002-05-13 00:16:03 +000084
sewardj018f7622002-05-15 21:13:39 +000085/* -----------------------------------------------------
86 Static client signal state (SCSS). This is the state
87 that the client thinks it has the kernel in.
88 SCSS records verbatim the client's settings. These
89 are mashed around only when SKSS is calculated from it.
90 -------------------------------------------------- */
sewardjb48e5002002-05-13 00:16:03 +000091
sewardj018f7622002-05-15 21:13:39 +000092typedef
93 struct {
94 void* scss_handler; /* VKI_SIG_DFL or VKI_SIG_IGN or ptr to
95 client's handler */
96 UInt scss_flags;
97 vki_ksigset_t scss_mask;
98 void* scss_restorer; /* god knows; we ignore it. */
99 }
100 SCSS_Per_Signal;
sewardjb48e5002002-05-13 00:16:03 +0000101
sewardj018f7622002-05-15 21:13:39 +0000102typedef
103 struct {
sewardj2342c972002-05-22 23:34:20 +0000104 /* per-signal info */
sewardj018f7622002-05-15 21:13:39 +0000105 SCSS_Per_Signal scss_per_sig[1+VKI_KNSIG];
sewardj2342c972002-05-22 23:34:20 +0000106
107 /* Signal delivery stack, if any. */
108 vki_kstack_t altstack;
109
sewardj018f7622002-05-15 21:13:39 +0000110 /* Additional elements to SCSS not stored here:
111 - for each thread, the thread's blocking mask
112 - for each thread in WaitSIG, the set of waited-on sigs
113 */
114 }
115 SCSS;
sewardjb48e5002002-05-13 00:16:03 +0000116
sewardj018f7622002-05-15 21:13:39 +0000117static SCSS vg_scss;
118
119
120/* -----------------------------------------------------
121 Static kernel signal state (SKSS). This is the state
122 that we have the kernel in. It is computed from SCSS.
123 -------------------------------------------------- */
124
125/* Let's do:
126 sigprocmask assigns to all thread masks
127 so that at least everything is always consistent
128 Flags:
129 SA_NOCLDSTOP -- passed to kernel
130 SA_ONESHOT or SA_RESETHAND -- required; abort if not set
131 SA_RESTART -- we observe this but set our handlers always to restart
132 SA_NOMASK or SA_NODEFER -- required to not be set; abort if set
133 SA_ONSTACK -- currently not supported; abort if set.
sewardjb48e5002002-05-13 00:16:03 +0000134*/
sewardjde4a1d02002-03-22 01:27:54 +0000135
sewardj77e466c2002-04-14 02:29:29 +0000136
sewardj018f7622002-05-15 21:13:39 +0000137typedef
138 struct {
139 void* skss_handler; /* VKI_SIG_DFL or VKI_SIG_IGN
140 or ptr to our handler */
141 UInt skss_flags;
142 /* There is no skss_mask, since we know that we will always ask
143 for all signals to be blocked in our one-and-only
144 sighandler. */
145 /* Also there is no skss_restorer. */
146 }
147 SKSS_Per_Signal;
sewardjde4a1d02002-03-22 01:27:54 +0000148
sewardj018f7622002-05-15 21:13:39 +0000149typedef
150 struct {
151 SKSS_Per_Signal skss_per_sig[1+VKI_KNSIG];
152 vki_ksigset_t skss_sigmask; /* process' blocked signal mask */
153 }
154 SKSS;
155
156static SKSS vg_skss;
sewardjde4a1d02002-03-22 01:27:54 +0000157
sewardj2e93c502002-04-12 11:12:52 +0000158
sewardj018f7622002-05-15 21:13:39 +0000159/* -----------------------------------------------------
160 Dynamic client signal state (DCSS). This holds transient
161 information about state of client signals.
162 -------------------------------------------------- */
sewardjb48e5002002-05-13 00:16:03 +0000163
sewardj018f7622002-05-15 21:13:39 +0000164typedef
165 struct {
166 /* True iff a signal has been received but not yet passed to
167 client. */
168 Bool dcss_sigpending[1+VKI_KNSIG];
169 /* If sigpending[] is True, has meaning:
170 VG_INVALID_THREADID -- to be passed to any suitable thread
171 other -- to be passed only to the specified thread. */
172 ThreadId dcss_destthread[1+VKI_KNSIG];
173 }
174 DCSS;
sewardjb48e5002002-05-13 00:16:03 +0000175
sewardj018f7622002-05-15 21:13:39 +0000176static DCSS vg_dcss;
sewardjb48e5002002-05-13 00:16:03 +0000177
178
sewardj018f7622002-05-15 21:13:39 +0000179/* ---------------------------------------------------------------------
180 Compute the SKSS required by the current SCSS.
181 ------------------------------------------------------------------ */
182
sewardj4f29ddf2002-05-03 22:29:04 +0000183static
sewardj018f7622002-05-15 21:13:39 +0000184void pp_SKSS ( void )
185{
186 Int sig;
187 VG_(printf)("\n\nSKSS:\n");
188 for (sig = 1; sig <= VKI_KNSIG; sig++) {
189 VG_(printf)("sig %d: handler 0x%x, flags 0x%x\n", sig,
190 vg_skss.skss_per_sig[sig].skss_handler,
191 vg_skss.skss_per_sig[sig].skss_flags );
sewardj77e466c2002-04-14 02:29:29 +0000192
sewardj018f7622002-05-15 21:13:39 +0000193 }
194 VG_(printf)("Global sigmask (63 .. 0) = 0x%x 0x%x\n",
195 vg_skss.skss_sigmask.ws[1],
196 vg_skss.skss_sigmask.ws[0] );
197}
198
199static __inline__
200Bool is_WaitSIGd_by_any_thread ( Int sig )
201{
202 ThreadId tid;
203 for (tid = 1; tid < VG_N_THREADS; tid++) {
204 if (VG_(threads)[tid].status != VgTs_WaitSIG)
205 continue;
206 if (VG_(ksigismember)( &VG_(threads)[tid].sigs_waited_for, sig ))
207 return True;
208 }
209 return False;
210}
211
212static __inline__
213Bool is_blocked_by_all_threads ( Int sig )
214{
215 ThreadId tid;
216 for (tid = 1; tid < VG_N_THREADS; tid++) {
217 if (VG_(threads)[tid].status == VgTs_Empty)
218 continue;
219 if (! VG_(ksigismember)( &VG_(threads)[tid].sig_mask, sig ))
220 return False;
221 }
222 return True;
223}
224
225
226/* This is the core, clever bit. Computation is as follows:
227
228 For each signal
229 handler = if client has a handler, then our handler
230 else if is WaitSIG'd by any thread, then our handler
231 else if client is DFL, then DFL
232 else (client must be IGN) IGN
233
234 blocked = if is blocked by all threads and not WaitSIG'd by
235 any thread
236 then BLOCKED
237 else UNBLOCKED
238*/
239static
240void calculate_SKSS_from_SCSS ( SKSS* dst )
241{
242 Int sig;
243 void* skss_handler;
244 void* scss_handler;
245 Bool iz_WaitSIGd_by_any_thread;
246 Bool iz_blocked_by_all_threads;
247 Bool skss_blocked;
248 UInt scss_flags;
249 UInt skss_flags;
250
251 VG_(ksigemptyset)( &dst->skss_sigmask );
252
253 for (sig = 1; sig <= VKI_KNSIG; sig++) {
254
255 /* Calculate kernel handler and blockedness for sig, as per rules
256 in above comment. */
257
258 iz_WaitSIGd_by_any_thread = is_WaitSIGd_by_any_thread(sig);
259 iz_blocked_by_all_threads = is_blocked_by_all_threads(sig);
260
261 scss_handler = vg_scss.scss_per_sig[sig].scss_handler;
262 scss_flags = vg_scss.scss_per_sig[sig].scss_flags;
263
264 /* Restorer */
265 /*
266 Doesn't seem like we can spin this one.
267 if (vg_scss.scss_per_sig[sig].scss_restorer != NULL)
268 VG_(unimplemented)
269 ("sigactions with non-NULL .sa_restorer field");
270 */
271
272 /* Handler */
273
274 if (scss_handler != VKI_SIG_DFL && scss_handler != VKI_SIG_IGN) {
275 skss_handler = &vg_oursignalhandler;
276 } else
277 if (iz_WaitSIGd_by_any_thread) {
278 skss_handler = &vg_oursignalhandler;
279 } else
280 if (scss_handler == VKI_SIG_DFL) {
281 skss_handler = VKI_SIG_DFL;
282 }
283 else {
284 vg_assert(scss_handler == VKI_SIG_IGN);
285 skss_handler = VKI_SIG_IGN;
286 }
287
288 /* Blockfulness */
289
290 skss_blocked
291 = iz_blocked_by_all_threads && !iz_WaitSIGd_by_any_thread;
292
293 /* Flags */
294
295 skss_flags = 0;
296 /* SA_NOCLDSTOP: pass to kernel */
297 if (scss_flags & VKI_SA_NOCLDSTOP)
298 skss_flags |= VKI_SA_NOCLDSTOP;
299 /* SA_ONESHOT: ignore client setting */
300 /*
301 if (!(scss_flags & VKI_SA_ONESHOT))
302 VG_(unimplemented)
303 ("sigactions without SA_ONESHOT");
304 vg_assert(scss_flags & VKI_SA_ONESHOT);
305 skss_flags |= VKI_SA_ONESHOT;
306 */
307 /* SA_RESTART: ignore client setting and set for us */
308 skss_flags |= VKI_SA_RESTART;
309 /* SA_NOMASK: not allowed */
310 /*
311 .. well, ignore it.
312 if (scss_flags & VKI_SA_NOMASK)
313 VG_(unimplemented)
314 ("sigactions with SA_NOMASK");
315 vg_assert(!(scss_flags & VKI_SA_NOMASK));
316 */
sewardj2342c972002-05-22 23:34:20 +0000317 /* SA_ONSTACK: client setting is irrelevant here */
318 /*
sewardj018f7622002-05-15 21:13:39 +0000319 if (scss_flags & VKI_SA_ONSTACK)
320 VG_(unimplemented)
321 ("signals on an alternative stack (SA_ONSTACK)");
322 vg_assert(!(scss_flags & VKI_SA_ONSTACK));
sewardj2342c972002-05-22 23:34:20 +0000323 */
sewardj018f7622002-05-15 21:13:39 +0000324 /* ... but WE ask for on-stack ourselves ... */
325 skss_flags |= VKI_SA_ONSTACK;
326
327 /* Create SKSS entry for this signal. */
328
329 if (skss_blocked
330 && sig != VKI_SIGKILL && sig != VKI_SIGSTOP)
331 VG_(ksigaddset)( &dst->skss_sigmask, sig );
332
sewardj6a3c26e2002-05-23 17:09:43 +0000333 if (sig != VKI_SIGKILL && sig != VKI_SIGSTOP)
334 dst->skss_per_sig[sig].skss_handler = skss_handler;
335 else
336 dst->skss_per_sig[sig].skss_handler = VKI_SIG_DFL;
337
sewardj018f7622002-05-15 21:13:39 +0000338 dst->skss_per_sig[sig].skss_flags = skss_flags;
339 }
340
341 /* Sanity checks. */
342 vg_assert(dst->skss_per_sig[VKI_SIGKILL].skss_handler
343 == VKI_SIG_DFL);
344 vg_assert(dst->skss_per_sig[VKI_SIGSTOP].skss_handler
345 == VKI_SIG_DFL);
346 vg_assert(!VG_(ksigismember)( &dst->skss_sigmask, VKI_SIGKILL ));
347 vg_assert(!VG_(ksigismember)( &dst->skss_sigmask, VKI_SIGSTOP ));
348
349 if (0)
350 pp_SKSS();
351}
352
353
354/* ---------------------------------------------------------------------
355 After a possible SCSS change, update SKSS and the kernel itself.
356 ------------------------------------------------------------------ */
357
358/* IMPORTANT NOTE: to avoid race conditions, we must always enter here
359 with ALL KERNEL SIGNALS BLOCKED !
360*/
361void VG_(handle_SCSS_change) ( Bool force_update )
362{
363 Int res, sig;
364 SKSS skss_old;
365 vki_ksigaction ksa, ksa_old;
366
367# ifdef DEBUG_SIGNALS
368 vki_ksigset_t test_sigmask;
369 res = VG_(ksigprocmask)( VKI_SIG_SETMASK /*irrelevant*/,
370 NULL, &test_sigmask );
371 vg_assert(res == 0);
372 /* The kernel never says that SIGKILL or SIGSTOP are masked. It is
373 correct! So we fake it here for the purposes only of
374 assertion. */
375 VG_(ksigaddset)( &test_sigmask, VKI_SIGKILL );
376 VG_(ksigaddset)( &test_sigmask, VKI_SIGSTOP );
377 vg_assert(VG_(kisfullsigset)( &test_sigmask ));
378# endif
379
380 /* Remember old SKSS and calculate new one. */
381 skss_old = vg_skss;
382 calculate_SKSS_from_SCSS ( &vg_skss );
383
384 /* Compare the new SKSS entries vs the old ones, and update kernel
385 where they differ. */
386 for (sig = 1; sig <= VKI_KNSIG; sig++) {
387
388 /* Trying to do anything with SIGKILL is pointless; just ignore
389 it. */
390 if (sig == VKI_SIGKILL || sig == VKI_SIGSTOP)
391 continue;
392
393 /* Aside: take the opportunity to clean up DCSS: forget about any
394 pending signals directed at dead threads. */
395 if (vg_dcss.dcss_sigpending[sig]
396 && vg_dcss.dcss_destthread[sig] != VG_INVALID_THREADID) {
397 ThreadId tid = vg_dcss.dcss_destthread[sig];
398 vg_assert(VG_(is_valid_or_empty_tid)(tid));
399 if (VG_(threads)[tid].status == VgTs_Empty) {
400 vg_dcss.dcss_sigpending[sig] = False;
401 vg_dcss.dcss_destthread[sig] = VG_INVALID_THREADID;
402 if (VG_(clo_trace_signals))
403 VG_(message)(Vg_DebugMsg,
404 "discarding pending signal %d due to thread %d exiting",
405 sig, tid );
406 }
407 }
408
409 /* End of the Aside. Now the Main Business. */
410
411 if (!force_update) {
412 if ((skss_old.skss_per_sig[sig].skss_handler
413 == vg_skss.skss_per_sig[sig].skss_handler)
414 && (skss_old.skss_per_sig[sig].skss_flags
415 == vg_skss.skss_per_sig[sig].skss_flags))
416 /* no difference */
417 continue;
418 }
419
420 ksa.ksa_handler = vg_skss.skss_per_sig[sig].skss_handler;
421 ksa.ksa_flags = vg_skss.skss_per_sig[sig].skss_flags;
422 vg_assert(ksa.ksa_flags & VKI_SA_ONSTACK);
423 VG_(ksigfillset)( &ksa.ksa_mask );
424 VG_(ksigdelset)( &ksa.ksa_mask, VKI_SIGKILL );
425 VG_(ksigdelset)( &ksa.ksa_mask, VKI_SIGSTOP );
426 ksa.ksa_restorer = NULL;
427
428 if (VG_(clo_trace_signals))
429 VG_(message)(Vg_DebugMsg,
430 "setting ksig %d to: hdlr 0x%x, flags 0x%x, "
431 "mask(63..0) 0x%x 0x%x",
432 sig, ksa.ksa_handler,
433 ksa.ksa_flags,
434 ksa.ksa_mask.ws[1],
435 ksa.ksa_mask.ws[0]
436 );
437
438 res = VG_(ksigaction)( sig, &ksa, &ksa_old );
439 vg_assert(res == 0);
440
441 /* Since we got the old sigaction more or less for free, might
442 as well extract the maximum sanity-check value from it. */
443 if (!force_update) {
444 vg_assert(ksa_old.ksa_handler
445 == skss_old.skss_per_sig[sig].skss_handler);
446 vg_assert(ksa_old.ksa_flags
447 == skss_old.skss_per_sig[sig].skss_flags);
448 vg_assert(ksa_old.ksa_restorer
449 == NULL);
450 VG_(ksigaddset)( &ksa_old.ksa_mask, VKI_SIGKILL );
451 VG_(ksigaddset)( &ksa_old.ksa_mask, VKI_SIGSTOP );
452 vg_assert(VG_(kisfullsigset)( &ksa_old.ksa_mask ));
453 }
454 }
455
456 /* Just set the new sigmask, even if it's no different from the
457 old, since we have to do this anyway, to unblock the host
458 signals. */
459 if (VG_(clo_trace_signals))
460 VG_(message)(Vg_DebugMsg,
461 "setting kmask(63..0) to 0x%x 0x%x",
462 vg_skss.skss_sigmask.ws[1],
463 vg_skss.skss_sigmask.ws[0]
464 );
465
466 VG_(restore_all_host_signals)( &vg_skss.skss_sigmask );
467}
468
469
470/* ---------------------------------------------------------------------
471 Update/query SCSS in accordance with client requests.
472 ------------------------------------------------------------------ */
473
sewardj2342c972002-05-22 23:34:20 +0000474/* Logic for this alt-stack stuff copied directly from do_sigaltstack
475 in kernel/signal.[ch] */
476
477/* True if we are on the alternate signal stack. */
478static Int on_sig_stack ( Addr m_esp )
479{
480 return (m_esp - (Addr)vg_scss.altstack.ss_sp
481 < vg_scss.altstack.ss_size);
482}
483
484static Int sas_ss_flags ( Addr m_esp )
485{
486 return (vg_scss.altstack.ss_size == 0
487 ? VKI_SS_DISABLE
488 : on_sig_stack(m_esp) ? VKI_SS_ONSTACK : 0);
489}
490
491
492void VG_(do__NR_sigaltstack) ( ThreadId tid )
493{
494 vki_kstack_t* ss;
495 vki_kstack_t* oss;
496 Addr m_esp;
497
498 vg_assert(VG_(is_valid_tid)(tid));
499 ss = (vki_kstack_t*)(VG_(threads)[tid].m_ebx);
500 oss = (vki_kstack_t*)(VG_(threads)[tid].m_ecx);
501 m_esp = VG_(threads)[tid].m_esp;
502
503 if (VG_(clo_trace_signals))
504 VG_(message)(Vg_DebugExtraMsg,
505 "__NR_sigaltstack: tid %d, "
506 "ss 0x%x, oss 0x%x (current %%esp %p)",
507 tid, (UInt)ss, (UInt)oss, (UInt)m_esp );
508
509 if (oss != NULL) {
510 oss->ss_sp = vg_scss.altstack.ss_sp;
511 oss->ss_size = vg_scss.altstack.ss_size;
512 oss->ss_flags = sas_ss_flags(m_esp);
513 }
514
515 if (ss != NULL) {
516 if (on_sig_stack(VG_(threads)[tid].m_esp)) {
517 SET_EAX(tid, -VKI_EPERM);
518 return;
519 }
520 if (ss->ss_flags != VKI_SS_DISABLE
521 && ss->ss_flags != VKI_SS_ONSTACK
522 && ss->ss_flags != 0) {
523 SET_EAX(tid, -VKI_EINVAL);
524 return;
525 }
526 if (ss->ss_flags == VKI_SS_DISABLE) {
527 vg_scss.altstack.ss_size = 0;
528 vg_scss.altstack.ss_sp = NULL;
529 } else {
530 if (ss->ss_size < VKI_MINSIGSTKSZ) {
531 SET_EAX(tid, -VKI_ENOMEM);
532 return;
533 }
534 }
535 vg_scss.altstack.ss_sp = ss->ss_sp;
536 vg_scss.altstack.ss_size = ss->ss_size;
537 }
538 SET_EAX(tid, 0);
539}
540
541
sewardj018f7622002-05-15 21:13:39 +0000542void VG_(do__NR_sigaction) ( ThreadId tid )
543{
544 Int signo;
545 vki_ksigaction* new_act;
546 vki_ksigaction* old_act;
547 vki_ksigset_t irrelevant_sigmask;
548
549 vg_assert(VG_(is_valid_tid)(tid));
550 signo = VG_(threads)[tid].m_ebx; /* int sigNo */
551 new_act = (vki_ksigaction*)(VG_(threads)[tid].m_ecx);
552 old_act = (vki_ksigaction*)(VG_(threads)[tid].m_edx);
553
554 if (VG_(clo_trace_signals))
555 VG_(message)(Vg_DebugExtraMsg,
556 "__NR_sigaction: tid %d, sigNo %d, "
557 "new 0x%x, old 0x%x, new flags 0x%x",
558 tid, signo, (UInt)new_act, (UInt)old_act,
559 (UInt)(new_act ? new_act->ksa_flags : 0) );
560
561 /* Rule out various error conditions. The aim is to ensure that if
562 when the call is passed to the kernel it will definitely
563 succeed. */
564
565 /* Reject out-of-range signal numbers. */
566 if (signo < 1 || signo > VKI_KNSIG) goto bad_signo;
567
568 /* Reject attempts to set a handler (or set ignore) for SIGKILL. */
569 if ( (signo == VKI_SIGKILL || signo == VKI_SIGSTOP)
570 && new_act
571 && new_act->ksa_handler != VKI_SIG_DFL)
572 goto bad_sigkill_or_sigstop;
573
574 /* If the client supplied non-NULL old_act, copy the relevant SCSS
575 entry into it. */
576 if (old_act) {
577 old_act->ksa_handler = vg_scss.scss_per_sig[signo].scss_handler;
578 old_act->ksa_flags = vg_scss.scss_per_sig[signo].scss_flags;
579 old_act->ksa_mask = vg_scss.scss_per_sig[signo].scss_mask;
580 old_act->ksa_restorer = vg_scss.scss_per_sig[signo].scss_restorer;
581 }
582
583 /* And now copy new SCSS entry from new_act. */
584 if (new_act) {
585 vg_scss.scss_per_sig[signo].scss_handler = new_act->ksa_handler;
586 vg_scss.scss_per_sig[signo].scss_flags = new_act->ksa_flags;
587 vg_scss.scss_per_sig[signo].scss_mask = new_act->ksa_mask;
588 vg_scss.scss_per_sig[signo].scss_restorer = new_act->ksa_restorer;
589 }
590
591 /* All happy bunnies ... */
592 if (new_act) {
593 VG_(block_all_host_signals)( &irrelevant_sigmask );
594 VG_(handle_SCSS_change)( False /* lazy update */ );
595 }
596 SET_EAX(tid, 0);
597 return;
598
599 bad_signo:
njn25e49d8e72002-09-23 09:36:25 +0000600 if (VG_(needs).core_errors)
601 VG_(message)(Vg_UserMsg,
602 "Warning: bad signal number %d in __NR_sigaction.",
603 signo);
sewardj018f7622002-05-15 21:13:39 +0000604 SET_EAX(tid, -VKI_EINVAL);
605 return;
606
607 bad_sigkill_or_sigstop:
njn25e49d8e72002-09-23 09:36:25 +0000608 if (VG_(needs).core_errors)
609 VG_(message)(Vg_UserMsg,
610 "Warning: attempt to set %s handler in __NR_sigaction.",
611 signo == VKI_SIGKILL ? "SIGKILL" : "SIGSTOP" );
sewardj018f7622002-05-15 21:13:39 +0000612
613 SET_EAX(tid, -VKI_EINVAL);
614 return;
615}
616
617
618static
619void do_sigprocmask_bitops ( Int vki_how,
620 vki_ksigset_t* orig_set,
621 vki_ksigset_t* modifier )
622{
623 switch (vki_how) {
624 case VKI_SIG_BLOCK:
625 VG_(ksigaddset_from_set)( orig_set, modifier );
626 break;
627 case VKI_SIG_UNBLOCK:
628 VG_(ksigdelset_from_set)( orig_set, modifier );
629 break;
630 case VKI_SIG_SETMASK:
631 *orig_set = *modifier;
632 break;
633 default:
njne427a662002-10-02 11:08:25 +0000634 VG_(core_panic)("do_sigprocmask_bitops");
sewardj018f7622002-05-15 21:13:39 +0000635 break;
636 }
637}
638
639/* Handle blocking mask set/get uniformly for threads and process as a
640 whole. If tid==VG_INVALID_THREADID, this is really
641 __NR_sigprocmask, in which case we set the masks for all threads to
642 the "set" and return in "oldset" that from the root thread (1).
643 Otherwise, tid will denote a valid thread, in which case we just
644 set/get its mask.
645
646 Note that the thread signal masks are an implicit part of SCSS,
647 which is why this routine is allowed to mess with them.
648*/
649static
650void do_setmask ( ThreadId tid,
651 Int how,
652 vki_ksigset_t* newset,
653 vki_ksigset_t* oldset )
654{
655 vki_ksigset_t irrelevant_sigmask;
656
657 if (VG_(clo_trace_signals))
sewardja464e5c2002-05-23 17:34:49 +0000658 VG_(message)(Vg_DebugExtraMsg,
sewardj3a951cf2002-05-15 22:25:47 +0000659 "do_setmask: tid = %d (%d means ALL), how = %d (%s), set = %p",
sewardj018f7622002-05-15 21:13:39 +0000660 tid,
sewardj3a951cf2002-05-15 22:25:47 +0000661 VG_INVALID_THREADID,
sewardj018f7622002-05-15 21:13:39 +0000662 how,
663 how==VKI_SIG_BLOCK ? "SIG_BLOCK" : (
664 how==VKI_SIG_UNBLOCK ? "SIG_UNBLOCK" : (
665 how==VKI_SIG_SETMASK ? "SIG_SETMASK" : "???")),
666 newset
667 );
668
669 if (tid == VG_INVALID_THREADID) {
670 /* Behave as if __NR_sigprocmask. */
671 if (oldset) {
672 /* A bit fragile. Should do better here really. */
673 vg_assert(VG_(threads)[1].status != VgTs_Empty);
674 *oldset = VG_(threads)[1].sig_mask;
675 }
676 if (newset) {
677 ThreadId tidd;
678 for (tidd = 1; tidd < VG_N_THREADS; tidd++) {
679 if (VG_(threads)[tidd].status == VgTs_Empty)
680 continue;
681 do_sigprocmask_bitops (
682 how, &VG_(threads)[tidd].sig_mask, newset );
683 }
684 }
685 } else {
686 /* Just do this thread. */
687 vg_assert(VG_(is_valid_tid)(tid));
688 if (oldset)
689 *oldset = VG_(threads)[tid].sig_mask;
690 if (newset)
691 do_sigprocmask_bitops (
692 how, &VG_(threads)[tid].sig_mask, newset );
693 }
694
695 if (newset) {
696 VG_(block_all_host_signals)( &irrelevant_sigmask );
697 VG_(handle_SCSS_change)( False /* lazy update */ );
698 }
699}
700
701
702void VG_(do__NR_sigprocmask) ( ThreadId tid,
703 Int how,
704 vki_ksigset_t* set,
705 vki_ksigset_t* oldset )
706{
707 if (how == VKI_SIG_BLOCK || how == VKI_SIG_UNBLOCK
708 || how == VKI_SIG_SETMASK) {
709 vg_assert(VG_(is_valid_tid)(tid));
710 do_setmask ( VG_INVALID_THREADID, how, set, oldset );
711 /* Syscall returns 0 (success) to its thread. */
712 SET_EAX(tid, 0);
713 } else {
714 VG_(message)(Vg_DebugMsg,
715 "sigprocmask: unknown `how' field %d", how);
716 SET_EAX(tid, -VKI_EINVAL);
717 }
718}
719
720
721void VG_(do_pthread_sigmask_SCSS_upd) ( ThreadId tid,
722 Int how,
723 vki_ksigset_t* set,
724 vki_ksigset_t* oldset )
725{
726 /* Assume that how has been validated by caller. */
727 vg_assert(how == VKI_SIG_BLOCK || how == VKI_SIG_UNBLOCK
728 || how == VKI_SIG_SETMASK);
729 vg_assert(VG_(is_valid_tid)(tid));
730 do_setmask ( tid, how, set, oldset );
731 /* The request return code is set in do_pthread_sigmask */
732}
733
734
735void VG_(send_signal_to_thread) ( ThreadId thread, Int sig )
736{
737 Int res;
738 vg_assert(VG_(is_valid_tid)(thread));
739 vg_assert(sig >= 1 && sig <= VKI_KNSIG);
740
741 switch ((UInt)(vg_scss.scss_per_sig[sig].scss_handler)) {
742
sewardjc9792e32002-05-21 00:05:10 +0000743 case ((UInt)VKI_SIG_IGN):
sewardj018f7622002-05-15 21:13:39 +0000744 if (VG_(clo_trace_signals))
745 VG_(message)(Vg_DebugMsg,
746 "send_signal %d to_thread %d: IGN, ignored", sig, thread );
747 break;
748
sewardjc9792e32002-05-21 00:05:10 +0000749 case ((UInt)VKI_SIG_DFL):
sewardj018f7622002-05-15 21:13:39 +0000750 /* This is the tricky case. Since we don't handle default
751 actions, the simple thing is to send someone round to the
752 front door and signal there. Then the kernel will do
753 whatever it does with the default action. */
sewardjdcaf3122002-09-30 23:12:33 +0000754 res = VG_(kkill)( VG_(getpid)(), sig );
sewardj018f7622002-05-15 21:13:39 +0000755 vg_assert(res == 0);
756 break;
757
758 default:
759 if (!vg_dcss.dcss_sigpending[sig]) {
760 vg_dcss.dcss_sigpending[sig] = True;
761 vg_dcss.dcss_destthread[sig] = thread;
762 if (VG_(clo_trace_signals))
763 VG_(message)(Vg_DebugMsg,
764 "send_signal %d to_thread %d: now pending", sig, thread );
765 } else {
766 if (vg_dcss.dcss_destthread[sig] == thread) {
767 if (VG_(clo_trace_signals))
768 VG_(message)(Vg_DebugMsg,
769 "send_signal %d to_thread %d: already pending ... "
770 "discarded", sig, thread );
771 } else {
772 if (VG_(clo_trace_signals))
773 VG_(message)(Vg_DebugMsg,
774 "send_signal %d to_thread %d: was pending for %d, "
775 "now pending for %d",
776 sig, thread, vg_dcss.dcss_destthread[sig], thread );
777 vg_dcss.dcss_destthread[sig] = thread;
778 }
779 }
780 }
781}
782
783
sewardjefbfcdf2002-06-19 17:35:45 +0000784/* Store in set the signals which could be delivered to this thread
785 right now (since they are pending) but cannot be, because the
786 thread has masked them out. */
787void VG_(do_sigpending) ( ThreadId tid, vki_ksigset_t* set )
788{
789 Int sig, res;
790 Bool maybe_pend;
791 vki_ksigset_t process_pending;
792
793 /* Get the set of signals which are pending for the process as a
794 whole. */
sewardjdcaf3122002-09-30 23:12:33 +0000795 res = VG_(ksigpending)( &process_pending );
sewardjefbfcdf2002-06-19 17:35:45 +0000796 vg_assert(res == 0);
797
798 VG_(ksigemptyset)(set);
799 for (sig = 1; sig <= VKI_KNSIG; sig++) {
800
801 /* Figure out if the signal could be pending for this thread.
802 There are two cases. */
803 maybe_pend = False;
804
805 /* Case 1: perhaps the signal is pending for the process as a
806 whole -- that is, is blocked even valgrind's signal
807 handler. */
808 if (VG_(ksigismember)( &process_pending, sig ))
809 maybe_pend = True;
810
811 /* Case 2: the signal has been collected by our handler and is
812 now awaiting disposition inside valgrind. */
813 if (/* is it pending at all? */
814 vg_dcss.dcss_sigpending[sig]
815 &&
816 /* check it is not specifically directed to some other thread */
817 (vg_dcss.dcss_destthread[sig] == VG_INVALID_THREADID
818 || vg_dcss.dcss_destthread[sig] == tid)
819 )
820 maybe_pend = True;
821
822 if (!maybe_pend)
823 continue; /* this signal just ain't pending! */
824
825 /* Check other necessary conditions now ... */
826
827 if (VG_(ksigismember)( &VG_(threads)[tid].sigs_waited_for, sig ))
828 continue; /* tid is sigwaiting for sig, so will never be
829 offered to a handler */
830 if (! VG_(ksigismember)( &VG_(threads)[tid].sig_mask, sig ))
831 continue; /* not blocked in this thread */
832
833 /* Ok, sig could be delivered to this thread if only it wasn't
834 masked out. So we add it to set. */
835 VG_(ksigaddset)( set, sig );
836 }
837}
838
839
sewardj018f7622002-05-15 21:13:39 +0000840/* ---------------------------------------------------------------------
841 LOW LEVEL STUFF TO DO WITH SIGNALS: IMPLEMENTATION
842 ------------------------------------------------------------------ */
sewardj77e466c2002-04-14 02:29:29 +0000843
sewardj2e93c502002-04-12 11:12:52 +0000844/* ---------------------------------------------------------------------
845 Handy utilities to block/restore all host signals.
846 ------------------------------------------------------------------ */
847
848/* Block all host signals, dumping the old mask in *saved_mask. */
849void VG_(block_all_host_signals) ( /* OUT */ vki_ksigset_t* saved_mask )
850{
851 Int ret;
852 vki_ksigset_t block_procmask;
853 VG_(ksigfillset)(&block_procmask);
854 ret = VG_(ksigprocmask)
855 (VKI_SIG_SETMASK, &block_procmask, saved_mask);
856 vg_assert(ret == 0);
857}
858
859/* Restore the blocking mask using the supplied saved one. */
sewardj018f7622002-05-15 21:13:39 +0000860void VG_(restore_all_host_signals) ( /* IN */ vki_ksigset_t* saved_mask )
sewardj2e93c502002-04-12 11:12:52 +0000861{
862 Int ret;
863 ret = VG_(ksigprocmask)(VKI_SIG_SETMASK, saved_mask, NULL);
864 vg_assert(ret == 0);
865}
sewardjde4a1d02002-03-22 01:27:54 +0000866
867
868/* ---------------------------------------------------------------------
869 The signal simulation proper. A simplified version of what the
870 Linux kernel does.
871 ------------------------------------------------------------------ */
872
873/* A structure in which to save the application's registers
874 during the execution of signal handlers. */
875
876typedef
877 struct {
sewardjf247eae2002-09-27 00:46:59 +0000878 /* These 4 are parameters to the signal handler. The order of
879 them is important, since this whole struct is pushed onto the
880 client's stack at delivery time. The first 4 words -- which
881 will be at the top of the stack -- constitute 4 arg words to
882 the handler. */
883
884 /* Sig handler's (bogus) return address */
885 Addr retaddr;
886 /* The arg to the sig handler. We need to inspect this after
887 the handler returns, but it's unreasonable to assume that the
888 handler won't change it. So we keep a second copy of it in
889 sigNo_private. */
890 Int sigNo;
891 /* ptr to siginfo_t; NULL for now. */
892 Addr psigInfo;
893 /* ptr to ucontext; NULL for now. */
894 Addr puContext;
895
896 /* The rest are private fields which the handler is unaware of. */
897
sewardj2e93c502002-04-12 11:12:52 +0000898 /* Sanity check word. */
sewardjde4a1d02002-03-22 01:27:54 +0000899 UInt magicPI;
sewardjf247eae2002-09-27 00:46:59 +0000900 /* Safely-saved version of sigNo, as described above. */
901 Int sigNo_private;
sewardj2e93c502002-04-12 11:12:52 +0000902 /* Saved processor state. */
sewardjde4a1d02002-03-22 01:27:54 +0000903 UInt fpustate[VG_SIZE_OF_FPUSTATE_W];
904 UInt eax;
905 UInt ecx;
906 UInt edx;
907 UInt ebx;
908 UInt ebp;
909 UInt esp;
910 UInt esi;
911 UInt edi;
912 Addr eip;
913 UInt eflags;
sewardj2e93c502002-04-12 11:12:52 +0000914 /* Scheduler-private stuff: what was the thread's status prior to
915 delivering this signal? */
916 ThreadStatus status;
917 /* Sanity check word. Is the highest-addressed word; do not
918 move!*/
sewardjde4a1d02002-03-22 01:27:54 +0000919 UInt magicE;
920 }
sewardj2e93c502002-04-12 11:12:52 +0000921 VgSigFrame;
sewardjde4a1d02002-03-22 01:27:54 +0000922
923
924
sewardjde4a1d02002-03-22 01:27:54 +0000925/* Set up a stack frame (VgSigContext) for the client's signal
926 handler. This includes the signal number and a bogus return
927 address. */
928static
sewardj2e93c502002-04-12 11:12:52 +0000929void vg_push_signal_frame ( ThreadId tid, int sigNo )
sewardjde4a1d02002-03-22 01:27:54 +0000930{
931 Int i;
sewardj2342c972002-05-22 23:34:20 +0000932 Addr esp, esp_top_of_frame;
sewardj2e93c502002-04-12 11:12:52 +0000933 VgSigFrame* frame;
934 ThreadState* tst;
935
sewardj2342c972002-05-22 23:34:20 +0000936 vg_assert(sigNo >= 1 && sigNo <= VKI_KNSIG);
sewardj018f7622002-05-15 21:13:39 +0000937 vg_assert(VG_(is_valid_tid)(tid));
938 tst = & VG_(threads)[tid];
sewardj2e93c502002-04-12 11:12:52 +0000939
sewardj2342c972002-05-22 23:34:20 +0000940 if (/* this signal asked to run on an alt stack */
941 (vg_scss.scss_per_sig[sigNo].scss_flags & VKI_SA_ONSTACK)
942 && /* there is a defined and enabled alt stack, which we're not
943 already using. Logic from get_sigframe in
944 arch/i386/kernel/signal.c. */
945 sas_ss_flags(tst->m_esp) == 0
946 ) {
947 esp_top_of_frame
948 = (Addr)(vg_scss.altstack.ss_sp) + vg_scss.altstack.ss_size;
949 if (VG_(clo_trace_signals))
950 VG_(message)(Vg_DebugMsg,
951 "delivering signal %d to thread %d: on ALT STACK",
952 sigNo, tid );
njnfdc28af2003-02-24 10:36:48 +0000953
954 /* Signal delivery to skins */
955 VG_TRACK( pre_deliver_signal, tid, sigNo, /*alt_stack*/False );
956
sewardj2342c972002-05-22 23:34:20 +0000957 } else {
958 esp_top_of_frame = tst->m_esp;
njnfdc28af2003-02-24 10:36:48 +0000959
960 /* Signal delivery to skins */
961 VG_TRACK( pre_deliver_signal, tid, sigNo, /*alt_stack*/True );
sewardj2342c972002-05-22 23:34:20 +0000962 }
963
964 esp = esp_top_of_frame;
sewardj2e93c502002-04-12 11:12:52 +0000965 esp -= sizeof(VgSigFrame);
966 frame = (VgSigFrame*)esp;
njn25e49d8e72002-09-23 09:36:25 +0000967
968 /* For tracking memory events, indicate the entire frame has been
969 * allocated, but pretend that only the first four words are written */
970 VG_TRACK( new_mem_stack_signal, (Addr)frame, sizeof(VgSigFrame) );
971
sewardj2e93c502002-04-12 11:12:52 +0000972 /* Assert that the frame is placed correctly. */
973 vg_assert( (sizeof(VgSigFrame) & 0x3) == 0 );
974 vg_assert( ((Char*)(&frame->magicE)) + sizeof(UInt)
sewardj2342c972002-05-22 23:34:20 +0000975 == ((Char*)(esp_top_of_frame)) );
sewardj2e93c502002-04-12 11:12:52 +0000976
njn25e49d8e72002-09-23 09:36:25 +0000977 /* retaddr, sigNo, psigInfo, puContext fields are to be written */
978 VG_TRACK( pre_mem_write, Vg_CoreSignal, tst, "signal handler frame",
979 (Addr)esp, 16 );
sewardj2e93c502002-04-12 11:12:52 +0000980 frame->retaddr = (UInt)(&VG_(signalreturn_bogusRA));
981 frame->sigNo = sigNo;
sewardjf247eae2002-09-27 00:46:59 +0000982 frame->sigNo_private = sigNo;
sewardj2e93c502002-04-12 11:12:52 +0000983 frame->psigInfo = (Addr)NULL;
984 frame->puContext = (Addr)NULL;
985 frame->magicPI = 0x31415927;
986
sewardjde4a1d02002-03-22 01:27:54 +0000987 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
sewardj2e93c502002-04-12 11:12:52 +0000988 frame->fpustate[i] = tst->m_fpu[i];
sewardjde4a1d02002-03-22 01:27:54 +0000989
sewardj2e93c502002-04-12 11:12:52 +0000990 frame->eax = tst->m_eax;
991 frame->ecx = tst->m_ecx;
992 frame->edx = tst->m_edx;
993 frame->ebx = tst->m_ebx;
994 frame->ebp = tst->m_ebp;
995 frame->esp = tst->m_esp;
996 frame->esi = tst->m_esi;
997 frame->edi = tst->m_edi;
998 frame->eip = tst->m_eip;
999 frame->eflags = tst->m_eflags;
sewardjde4a1d02002-03-22 01:27:54 +00001000
sewardj2e93c502002-04-12 11:12:52 +00001001 frame->status = tst->status;
sewardjde4a1d02002-03-22 01:27:54 +00001002
sewardj2e93c502002-04-12 11:12:52 +00001003 frame->magicE = 0x27182818;
1004
1005 /* Set the thread so it will next run the handler. */
1006 tst->m_esp = esp;
sewardj018f7622002-05-15 21:13:39 +00001007 tst->m_eip = (Addr)vg_scss.scss_per_sig[sigNo].scss_handler;
sewardj2e93c502002-04-12 11:12:52 +00001008 /* This thread needs to be marked runnable, but we leave that the
1009 caller to do. */
sewardjde4a1d02002-03-22 01:27:54 +00001010
njn25e49d8e72002-09-23 09:36:25 +00001011 /* retaddr, sigNo, psigInfo, puContext fields have been written --
1012 at 0(%ESP) .. 12(%ESP) */
1013 VG_TRACK( post_mem_write, (Addr)esp, 16 );
sewardjde4a1d02002-03-22 01:27:54 +00001014
sewardjde4a1d02002-03-22 01:27:54 +00001015 /*
1016 VG_(printf)("pushed signal frame; %%ESP now = %p, next %%EBP = %p\n",
sewardj2e93c502002-04-12 11:12:52 +00001017 esp, tst->m_eip);
sewardjde4a1d02002-03-22 01:27:54 +00001018 */
1019}
1020
1021
1022/* Clear the signal frame created by vg_push_signal_frame, restore the
1023 simulated machine state, and return the signal number that the
1024 frame was for. */
1025static
sewardj2e93c502002-04-12 11:12:52 +00001026Int vg_pop_signal_frame ( ThreadId tid )
sewardjde4a1d02002-03-22 01:27:54 +00001027{
sewardj2e93c502002-04-12 11:12:52 +00001028 Addr esp;
sewardjde4a1d02002-03-22 01:27:54 +00001029 Int sigNo, i;
sewardj2e93c502002-04-12 11:12:52 +00001030 VgSigFrame* frame;
1031 ThreadState* tst;
sewardjde4a1d02002-03-22 01:27:54 +00001032
sewardj018f7622002-05-15 21:13:39 +00001033 vg_assert(VG_(is_valid_tid)(tid));
1034 tst = & VG_(threads)[tid];
sewardj2e93c502002-04-12 11:12:52 +00001035
sewardj54cacf02002-04-12 23:24:59 +00001036 /* Correctly reestablish the frame base address. */
sewardj2e93c502002-04-12 11:12:52 +00001037 esp = tst->m_esp;
sewardj54cacf02002-04-12 23:24:59 +00001038 frame = (VgSigFrame*)
1039 (esp -4 /* because the handler's RET pops the RA */
1040 +20 /* because signalreturn_bogusRA pushes 5 words */);
sewardj2e93c502002-04-12 11:12:52 +00001041
1042 vg_assert(frame->magicPI == 0x31415927);
1043 vg_assert(frame->magicE == 0x27182818);
sewardjde4a1d02002-03-22 01:27:54 +00001044 if (VG_(clo_trace_signals))
sewardjb48e5002002-05-13 00:16:03 +00001045 VG_(message)(Vg_DebugMsg,
1046 "vg_pop_signal_frame (thread %d): valid magic", tid);
sewardjde4a1d02002-03-22 01:27:54 +00001047
1048 /* restore machine state */
1049 for (i = 0; i < VG_SIZE_OF_FPUSTATE_W; i++)
sewardj2e93c502002-04-12 11:12:52 +00001050 tst->m_fpu[i] = frame->fpustate[i];
sewardjde4a1d02002-03-22 01:27:54 +00001051
sewardj2342c972002-05-22 23:34:20 +00001052 /* Mark the frame structure as nonaccessible. */
njn25e49d8e72002-09-23 09:36:25 +00001053 VG_TRACK( die_mem_stack_signal, (Addr)frame, sizeof(VgSigFrame) );
sewardjde4a1d02002-03-22 01:27:54 +00001054
1055 /* Restore machine state from the saved context. */
sewardj2e93c502002-04-12 11:12:52 +00001056 tst->m_eax = frame->eax;
1057 tst->m_ecx = frame->ecx;
1058 tst->m_edx = frame->edx;
1059 tst->m_ebx = frame->ebx;
1060 tst->m_ebp = frame->ebp;
1061 tst->m_esp = frame->esp;
1062 tst->m_esi = frame->esi;
1063 tst->m_edi = frame->edi;
1064 tst->m_eflags = frame->eflags;
1065 tst->m_eip = frame->eip;
sewardjf247eae2002-09-27 00:46:59 +00001066
1067 /* don't use the copy exposed to the handler; it might have changed
1068 it. */
1069 sigNo = frame->sigNo_private;
sewardj2e93c502002-04-12 11:12:52 +00001070
1071 /* And restore the thread's status to what it was before the signal
1072 was delivered. */
1073 tst->status = frame->status;
1074
njnfdc28af2003-02-24 10:36:48 +00001075 /* Notify skins */
1076 VG_TRACK( post_deliver_signal, tid, sigNo );
1077
sewardjde4a1d02002-03-22 01:27:54 +00001078 return sigNo;
1079}
1080
1081
1082/* A handler is returning. Restore the machine state from the stacked
1083 VgSigContext and continue with whatever was going on before the
sewardj77e466c2002-04-14 02:29:29 +00001084 handler ran. Returns the SA_RESTART syscall-restartability-status
1085 of the delivered signal. */
sewardjde4a1d02002-03-22 01:27:54 +00001086
sewardj77e466c2002-04-14 02:29:29 +00001087Bool VG_(signal_returns) ( ThreadId tid )
sewardjde4a1d02002-03-22 01:27:54 +00001088{
sewardj2e93c502002-04-12 11:12:52 +00001089 Int sigNo;
sewardjde4a1d02002-03-22 01:27:54 +00001090 vki_ksigset_t saved_procmask;
1091
1092 /* Block host signals ... */
sewardj2e93c502002-04-12 11:12:52 +00001093 VG_(block_all_host_signals)( &saved_procmask );
sewardjde4a1d02002-03-22 01:27:54 +00001094
sewardj2e93c502002-04-12 11:12:52 +00001095 /* Pop the signal frame and restore tid's status to what it was
1096 before the signal was delivered. */
1097 sigNo = vg_pop_signal_frame(tid);
sewardjde4a1d02002-03-22 01:27:54 +00001098
sewardjb48e5002002-05-13 00:16:03 +00001099 vg_assert(sigNo >= 1 && sigNo <= VKI_KNSIG);
sewardjde4a1d02002-03-22 01:27:54 +00001100
1101 /* Unlock and return. */
sewardj018f7622002-05-15 21:13:39 +00001102 VG_(restore_all_host_signals)( &saved_procmask );
sewardjde4a1d02002-03-22 01:27:54 +00001103
sewardj77e466c2002-04-14 02:29:29 +00001104 /* Scheduler now can resume this thread, or perhaps some other.
1105 Tell the scheduler whether or not any syscall interrupted by
1106 this signal should be restarted, if possible, or no. */
sewardj018f7622002-05-15 21:13:39 +00001107 return
1108 (vg_scss.scss_per_sig[sigNo].scss_flags & VKI_SA_RESTART)
1109 ? True
1110 : False;
sewardjde4a1d02002-03-22 01:27:54 +00001111}
1112
1113
1114/* Deliver all pending signals, by building stack frames for their
sewardj14e03422002-04-24 19:51:31 +00001115 handlers. Return True if any signals were delivered. */
sewardjb48e5002002-05-13 00:16:03 +00001116Bool VG_(deliver_signals) ( void )
sewardjde4a1d02002-03-22 01:27:54 +00001117{
sewardjde4a1d02002-03-22 01:27:54 +00001118 vki_ksigset_t saved_procmask;
sewardj2e93c502002-04-12 11:12:52 +00001119 Int sigNo;
sewardj018f7622002-05-15 21:13:39 +00001120 Bool found, scss_changed;
sewardjb48e5002002-05-13 00:16:03 +00001121 ThreadState* tst;
1122 ThreadId tid;
1123
sewardj018f7622002-05-15 21:13:39 +00001124 /* A cheap check. We don't need to have exclusive access to the
1125 pending array, because in the worst case, vg_oursignalhandler
1126 will add signals, causing us to return, thinking there are no
1127 signals to deliver, when in fact there are some. A subsequent
1128 call here will handle the signal(s) we missed. */
sewardjde4a1d02002-03-22 01:27:54 +00001129 found = False;
sewardjb48e5002002-05-13 00:16:03 +00001130 for (sigNo = 1; sigNo <= VKI_KNSIG; sigNo++)
sewardj018f7622002-05-15 21:13:39 +00001131 if (vg_dcss.dcss_sigpending[sigNo])
sewardjb48e5002002-05-13 00:16:03 +00001132 found = True;
sewardjde4a1d02002-03-22 01:27:54 +00001133
sewardj14e03422002-04-24 19:51:31 +00001134 if (!found) return False;
sewardjde4a1d02002-03-22 01:27:54 +00001135
1136 /* Now we have to do it properly. Get exclusive access by
1137 blocking all the host's signals. That means vg_oursignalhandler
1138 can't run whilst we are messing with stuff.
1139 */
sewardj018f7622002-05-15 21:13:39 +00001140 scss_changed = False;
sewardj2e93c502002-04-12 11:12:52 +00001141 VG_(block_all_host_signals)( &saved_procmask );
sewardjde4a1d02002-03-22 01:27:54 +00001142
sewardj2e93c502002-04-12 11:12:52 +00001143 /* Look for signals to deliver ... */
sewardjb48e5002002-05-13 00:16:03 +00001144 for (sigNo = 1; sigNo <= VKI_KNSIG; sigNo++) {
sewardj018f7622002-05-15 21:13:39 +00001145
1146 if (!vg_dcss.dcss_sigpending[sigNo])
1147 continue;
1148
sewardjb48e5002002-05-13 00:16:03 +00001149 /* sigNo is pending. Try to find a suitable thread to deliver
1150 it to. */
sewardjb48e5002002-05-13 00:16:03 +00001151 /* First off, are any threads in sigwait() for the signal?
1152 If so just give to one of them and have done. */
1153 for (tid = 1; tid < VG_N_THREADS; tid++) {
sewardj018f7622002-05-15 21:13:39 +00001154 tst = & VG_(threads)[tid];
sewardj0e357db2002-06-04 09:44:09 +00001155 /* Is tid waiting for a signal? If not, ignore. */
sewardjb48e5002002-05-13 00:16:03 +00001156 if (tst->status != VgTs_WaitSIG)
1157 continue;
sewardjb83b6a72002-06-04 10:34:40 +00001158 /* Is the signal directed at a specific thread other than
sewardj0e357db2002-06-04 09:44:09 +00001159 this one? If yes, ignore. */
1160 if (vg_dcss.dcss_destthread[sigNo] != VG_INVALID_THREADID
1161 && vg_dcss.dcss_destthread[sigNo] != tid)
1162 continue;
1163 /* Is tid waiting for the signal? If not, ignore. */
sewardjb48e5002002-05-13 00:16:03 +00001164 if (VG_(ksigismember)(&(tst->sigs_waited_for), sigNo))
1165 break;
1166 }
1167 if (tid < VG_N_THREADS) {
1168 UInt* sigwait_args;
sewardj018f7622002-05-15 21:13:39 +00001169 tst = & VG_(threads)[tid];
sewardjb48e5002002-05-13 00:16:03 +00001170 if (VG_(clo_trace_signals) || VG_(clo_trace_sched))
1171 VG_(message)(Vg_DebugMsg,
1172 "releasing thread %d from sigwait() due to signal %d",
1173 tid, sigNo );
1174 sigwait_args = (UInt*)(tst->m_eax);
1175 if (NULL != (UInt*)(sigwait_args[2])) {
1176 *(Int*)(sigwait_args[2]) = sigNo;
njn25e49d8e72002-09-23 09:36:25 +00001177 VG_TRACK( post_mem_write, (Addr)sigwait_args[2], sizeof(UInt));
sewardjb48e5002002-05-13 00:16:03 +00001178 }
sewardj018f7622002-05-15 21:13:39 +00001179 SET_EDX(tid, 0);
sewardjb48e5002002-05-13 00:16:03 +00001180 tst->status = VgTs_Runnable;
sewardj811d1412002-05-13 00:38:52 +00001181 VG_(ksigemptyset)(&tst->sigs_waited_for);
sewardj018f7622002-05-15 21:13:39 +00001182 scss_changed = True;
1183 vg_dcss.dcss_sigpending[sigNo] = False;
1184 vg_dcss.dcss_destthread[sigNo] = VG_INVALID_THREADID;
1185 /*paranoia*/
sewardjb48e5002002-05-13 00:16:03 +00001186 continue; /* for (sigNo = 1; ...) loop */
1187 }
1188
1189 /* Well, nobody appears to be sigwaiting for it. So we really
sewardj018f7622002-05-15 21:13:39 +00001190 are delivering the signal in the usual way. And that the
1191 client really has a handler for this thread! */
1192 vg_assert(vg_dcss.dcss_sigpending[sigNo]);
sewardj088f1182002-06-13 17:47:05 +00001193
1194 /* A recent addition, so as to stop seriously wierd progs dying
1195 at the following assertion (which this renders redundant,
1196 btw). */
1197 if (vg_scss.scss_per_sig[sigNo].scss_handler == VKI_SIG_IGN
1198 || vg_scss.scss_per_sig[sigNo].scss_handler == VKI_SIG_DFL) {
1199 /* Strange; perhaps the handler disappeared before we could
1200 deliver the signal. */
1201 VG_(message)(Vg_DebugMsg,
1202 "discarding signal %d for thread %d because handler missing",
1203 sigNo, tid );
1204 vg_dcss.dcss_sigpending[sigNo] = False;
1205 vg_dcss.dcss_destthread[sigNo] = VG_INVALID_THREADID;
1206 continue; /* for (sigNo = 1; ...) loop */
1207 }
1208
sewardj018f7622002-05-15 21:13:39 +00001209 vg_assert(vg_scss.scss_per_sig[sigNo].scss_handler != VKI_SIG_IGN
1210 && vg_scss.scss_per_sig[sigNo].scss_handler != VKI_SIG_DFL);
sewardjb48e5002002-05-13 00:16:03 +00001211
sewardj018f7622002-05-15 21:13:39 +00001212 tid = vg_dcss.dcss_destthread[sigNo];
sewardjb48e5002002-05-13 00:16:03 +00001213 vg_assert(tid == VG_INVALID_THREADID
1214 || VG_(is_valid_tid)(tid));
1215
1216 if (tid != VG_INVALID_THREADID) {
1217 /* directed to a specific thread; ensure it actually still
1218 exists ... */
sewardj018f7622002-05-15 21:13:39 +00001219 tst = & VG_(threads)[tid];
sewardjb48e5002002-05-13 00:16:03 +00001220 if (tst->status == VgTs_Empty) {
1221 /* dead, for whatever reason; ignore this signal */
1222 if (VG_(clo_trace_signals))
1223 VG_(message)(Vg_DebugMsg,
1224 "discarding signal %d for nonexistent thread %d",
1225 sigNo, tid );
sewardj018f7622002-05-15 21:13:39 +00001226 vg_dcss.dcss_sigpending[sigNo] = False;
1227 vg_dcss.dcss_destthread[sigNo] = VG_INVALID_THREADID;
sewardjb48e5002002-05-13 00:16:03 +00001228 continue; /* for (sigNo = 1; ...) loop */
njn25e49d8e72002-09-23 09:36:25 +00001229 } else if (VG_(ksigismember)(&(tst->sig_mask), sigNo)) {
1230 /* signal blocked in specific thread, so we can't
1231 deliver it just now */
1232 continue; /* for (sigNo = 1; ...) loop */
1233 }
sewardjb48e5002002-05-13 00:16:03 +00001234 } else {
1235 /* not directed to a specific thread, so search for a
1236 suitable candidate */
1237 for (tid = 1; tid < VG_N_THREADS; tid++) {
sewardj018f7622002-05-15 21:13:39 +00001238 tst = & VG_(threads)[tid];
sewardjb48e5002002-05-13 00:16:03 +00001239 if (tst->status != VgTs_Empty
1240 && !VG_(ksigismember)(&(tst->sig_mask), sigNo))
1241 break;
1242 }
1243 if (tid == VG_N_THREADS)
1244 /* All threads have this signal blocked, so we can't
1245 deliver it just now */
1246 continue; /* for (sigNo = 1; ...) loop */
1247 }
1248
1249 /* Ok, we can deliver signal sigNo to thread tid. */
sewardjde4a1d02002-03-22 01:27:54 +00001250
1251 if (VG_(clo_trace_signals))
sewardjb48e5002002-05-13 00:16:03 +00001252 VG_(message)(Vg_DebugMsg,"delivering signal %d to thread %d",
1253 sigNo, tid );
sewardjde4a1d02002-03-22 01:27:54 +00001254
1255 /* Create a signal delivery frame, and set the client's %ESP and
1256 %EIP so that when execution continues, we will enter the
1257 signal handler with the frame on top of the client's stack,
1258 as it expects. */
sewardjb48e5002002-05-13 00:16:03 +00001259 vg_assert(VG_(is_valid_tid)(tid));
sewardj2e93c502002-04-12 11:12:52 +00001260 vg_push_signal_frame ( tid, sigNo );
sewardj018f7622002-05-15 21:13:39 +00001261 VG_(threads)[tid].status = VgTs_Runnable;
sewardj2e93c502002-04-12 11:12:52 +00001262
sewardjde4a1d02002-03-22 01:27:54 +00001263 /* Signify that the signal has been delivered. */
sewardj018f7622002-05-15 21:13:39 +00001264 vg_dcss.dcss_sigpending[sigNo] = False;
1265 vg_dcss.dcss_destthread[sigNo] = VG_INVALID_THREADID;
1266
1267 if (vg_scss.scss_per_sig[sigNo].scss_flags & VKI_SA_ONESHOT) {
1268 /* Do the ONESHOT thing. */
1269 vg_scss.scss_per_sig[sigNo].scss_handler = VKI_SIG_DFL;
1270 scss_changed = True;
1271 }
sewardjde4a1d02002-03-22 01:27:54 +00001272 }
1273
1274 /* Unlock and return. */
sewardj018f7622002-05-15 21:13:39 +00001275 if (scss_changed) {
1276 /* handle_SCSS_change computes a new kernel blocking mask and
1277 applies that. */
1278 VG_(handle_SCSS_change)( False /* lazy update */ );
1279 } else {
1280 /* No SCSS change, so just restore the existing blocking
1281 mask. */
1282 VG_(restore_all_host_signals)( &saved_procmask );
sewardjb48e5002002-05-13 00:16:03 +00001283 }
sewardj018f7622002-05-15 21:13:39 +00001284
1285 return True;
sewardjb48e5002002-05-13 00:16:03 +00001286}
1287
1288
sewardjde4a1d02002-03-22 01:27:54 +00001289/* Receive a signal from the host, and either discard it or park it in
1290 the queue of pending signals. All other signals will be blocked
1291 when this handler runs. Runs with all host signals blocked, so as
1292 to have mutual exclusion when adding stuff to the queue. */
1293
sewardjb48e5002002-05-13 00:16:03 +00001294static
sewardj018f7622002-05-15 21:13:39 +00001295void vg_oursignalhandler ( Int sigNo )
sewardjde4a1d02002-03-22 01:27:54 +00001296{
sewardj872051c2002-07-13 12:12:56 +00001297 static UInt segv_warns = 0;
sewardj018f7622002-05-15 21:13:39 +00001298 ThreadId tid;
sewardj2e93c502002-04-12 11:12:52 +00001299 Int dummy_local;
sewardj018f7622002-05-15 21:13:39 +00001300 Bool sane;
sewardjde4a1d02002-03-22 01:27:54 +00001301 vki_ksigset_t saved_procmask;
1302
sewardj7a61d912002-04-25 01:27:35 +00001303 /*
1304 if (sigNo == VKI_SIGUSR1) {
1305 VG_(printf)("YOWZA! SIGUSR1\n\n");
1306 VG_(clo_trace_pthread_level) = 2;
1307 VG_(clo_trace_sched) = True;
1308 VG_(clo_trace_syscalls) = True;
1309 VG_(clo_trace_signals) = True;
1310 return;
1311 }
1312 */
1313
sewardjde4a1d02002-03-22 01:27:54 +00001314 if (VG_(clo_trace_signals)) {
1315 VG_(start_msg)(Vg_DebugMsg);
1316 VG_(add_to_msg)("signal %d arrived ... ", sigNo );
1317 }
sewardjb48e5002002-05-13 00:16:03 +00001318 vg_assert(sigNo >= 1 && sigNo <= VKI_KNSIG);
sewardjde4a1d02002-03-22 01:27:54 +00001319
1320 /* Sanity check. Ensure we're really running on the signal stack
1321 we asked for. */
1322 if ( !(
sewardj2e93c502002-04-12 11:12:52 +00001323 ((Char*)(&(VG_(sigstack)[0])) <= (Char*)(&dummy_local))
sewardjde4a1d02002-03-22 01:27:54 +00001324 &&
sewardj2e93c502002-04-12 11:12:52 +00001325 ((Char*)(&dummy_local) < (Char*)(&(VG_(sigstack)[10000])))
sewardjde4a1d02002-03-22 01:27:54 +00001326 )
1327 ) {
sewardj2e93c502002-04-12 11:12:52 +00001328 VG_(message)(Vg_DebugMsg,
1329 "FATAL: signal delivered on the wrong stack?!");
1330 VG_(message)(Vg_DebugMsg,
1331 "A possible workaround follows. Please tell me");
1332 VG_(message)(Vg_DebugMsg,
1333 "(jseward@acm.org) if the suggested workaround doesn't help.");
sewardjde4a1d02002-03-22 01:27:54 +00001334 VG_(unimplemented)
sewardj2e93c502002-04-12 11:12:52 +00001335 ("support for progs compiled with -p/-pg; "
1336 "rebuild your prog without -p/-pg");
sewardjde4a1d02002-03-22 01:27:54 +00001337 }
1338
sewardj2e93c502002-04-12 11:12:52 +00001339 vg_assert((Char*)(&(VG_(sigstack)[0])) <= (Char*)(&dummy_local));
1340 vg_assert((Char*)(&dummy_local) < (Char*)(&(VG_(sigstack)[10000])));
sewardjde4a1d02002-03-22 01:27:54 +00001341
sewardj2e93c502002-04-12 11:12:52 +00001342 VG_(block_all_host_signals)( &saved_procmask );
sewardjde4a1d02002-03-22 01:27:54 +00001343
sewardj018f7622002-05-15 21:13:39 +00001344 /* This is a sanity check. Either a signal has arrived because the
1345 client set a handler for it, or because some thread sigwaited on
1346 it. Establish that at least one of these is the case. */
1347 sane = False;
1348 if (vg_scss.scss_per_sig[sigNo].scss_handler != VKI_SIG_DFL
1349 && vg_scss.scss_per_sig[sigNo].scss_handler != VKI_SIG_IGN) {
1350 sane = True;
1351 } else {
1352 for (tid = 1; tid < VG_N_THREADS; tid++) {
1353 if (VG_(threads)[tid].status != VgTs_WaitSIG)
1354 continue;
1355 if (VG_(ksigismember)(&VG_(threads)[tid].sigs_waited_for, sigNo))
1356 sane = True;
1357 }
1358 }
1359 if (!sane) {
sewardjde4a1d02002-03-22 01:27:54 +00001360 if (VG_(clo_trace_signals)) {
1361 VG_(add_to_msg)("unexpected!");
1362 VG_(end_msg)();
1363 }
sewardj2e93c502002-04-12 11:12:52 +00001364 /* Note: we panic with all signals blocked here. Don't think
1365 that matters. */
njne427a662002-10-02 11:08:25 +00001366 VG_(core_panic)("vg_oursignalhandler: unexpected signal");
sewardjde4a1d02002-03-22 01:27:54 +00001367 }
sewardj018f7622002-05-15 21:13:39 +00001368 /* End of the sanity check. */
sewardjde4a1d02002-03-22 01:27:54 +00001369
1370 /* Decide what to do with it. */
sewardj018f7622002-05-15 21:13:39 +00001371 if (vg_dcss.dcss_sigpending[sigNo]) {
1372 /* pending; ignore it. */
sewardjde4a1d02002-03-22 01:27:54 +00001373 if (VG_(clo_trace_signals)) {
1374 VG_(add_to_msg)("already pending; discarded" );
1375 VG_(end_msg)();
1376 }
sewardj018f7622002-05-15 21:13:39 +00001377 } else {
sewardj2e93c502002-04-12 11:12:52 +00001378 /* Ok, we'd better deliver it to the client. */
sewardj2e93c502002-04-12 11:12:52 +00001379 /* Queue it up for delivery at some point in the future. */
sewardj018f7622002-05-15 21:13:39 +00001380 vg_dcss.dcss_sigpending[sigNo] = True;
1381 vg_dcss.dcss_destthread[sigNo] = VG_INVALID_THREADID;
sewardj2e93c502002-04-12 11:12:52 +00001382 if (VG_(clo_trace_signals)) {
1383 VG_(add_to_msg)("queued" );
1384 VG_(end_msg)();
sewardjde4a1d02002-03-22 01:27:54 +00001385 }
1386 }
1387
sewardj2e93c502002-04-12 11:12:52 +00001388 /* We've finished messing with the queue, so re-enable host
1389 signals. */
sewardj018f7622002-05-15 21:13:39 +00001390 VG_(restore_all_host_signals)( &saved_procmask );
sewardjde4a1d02002-03-22 01:27:54 +00001391
sewardj872051c2002-07-13 12:12:56 +00001392 if ( (sigNo == VKI_SIGSEGV || sigNo == VKI_SIGBUS
1393 || sigNo == VKI_SIGFPE || sigNo == VKI_SIGILL)
1394 &&
1395 VG_(scheduler_jmpbuf_valid)
1396 ) {
sewardj2e93c502002-04-12 11:12:52 +00001397 /* Can't continue; must longjmp back to the scheduler and thus
1398 enter the sighandler immediately. */
sewardjde4a1d02002-03-22 01:27:54 +00001399 VG_(longjmpd_on_signal) = sigNo;
sewardj2e93c502002-04-12 11:12:52 +00001400 __builtin_longjmp(VG_(scheduler_jmpbuf),1);
sewardjde4a1d02002-03-22 01:27:54 +00001401 }
sewardj872051c2002-07-13 12:12:56 +00001402
1403 if (sigNo == VKI_SIGSEGV && !VG_(scheduler_jmpbuf_valid)) {
1404 if (++segv_warns <= 3) {
1405 VG_(message)(Vg_UserMsg,
1406 "Warning: SIGSEGV not in user code; either from syscall kill()" );
1407 VG_(message)(Vg_UserMsg,
1408 " or possible Valgrind bug. "
1409 "This message is only shown 3 times." );
1410 }
1411 }
sewardjde4a1d02002-03-22 01:27:54 +00001412}
1413
1414
1415/* The outer insn loop calls here to reenable a host signal if
1416 vg_oursighandler longjmp'd.
1417*/
1418void VG_(unblock_host_signal) ( Int sigNo )
1419{
1420 Int ret;
1421 vki_ksigset_t set;
1422 VG_(ksigemptyset)(&set);
1423 ret = VG_(ksigaddset)(&set,sigNo);
1424 vg_assert(ret == 0);
1425 ret = VG_(ksigprocmask)(VKI_SIG_UNBLOCK,&set,NULL);
1426 vg_assert(ret == 0);
1427}
1428
1429
1430static __attribute((unused))
1431void pp_vg_ksigaction ( vki_ksigaction* sa )
1432{
1433 Int i;
1434 VG_(printf)("vg_ksigaction: handler %p, flags 0x%x, restorer %p\n",
sewardj9a199dc2002-04-14 13:01:38 +00001435 sa->ksa_handler, (UInt)sa->ksa_flags, sa->ksa_restorer);
sewardjde4a1d02002-03-22 01:27:54 +00001436 VG_(printf)("vg_ksigaction: { ");
sewardjb48e5002002-05-13 00:16:03 +00001437 for (i = 1; i <= VKI_KNSIG; i++)
sewardjde4a1d02002-03-22 01:27:54 +00001438 if (VG_(ksigismember(&(sa->ksa_mask),i)))
1439 VG_(printf)("%d ", i);
1440 VG_(printf)("}\n");
1441}
1442
1443
sewardj018f7622002-05-15 21:13:39 +00001444/* At startup, copy the process' real signal state to the SCSS.
1445 Whilst doing this, block all real signals. Then calculate SKSS and
1446 set the kernel to that. Also initialise DCSS.
sewardjde4a1d02002-03-22 01:27:54 +00001447*/
1448void VG_(sigstartup_actions) ( void )
1449{
1450 Int i, ret;
1451
sewardjde4a1d02002-03-22 01:27:54 +00001452 vki_ksigset_t saved_procmask;
1453 vki_kstack_t altstack_info;
1454 vki_ksigaction sa;
1455
sewardj2e93c502002-04-12 11:12:52 +00001456 /* VG_(printf)("SIGSTARTUP\n"); */
sewardjde4a1d02002-03-22 01:27:54 +00001457 /* Block all signals.
1458 saved_procmask remembers the previous mask. */
sewardj2e93c502002-04-12 11:12:52 +00001459 VG_(block_all_host_signals)( &saved_procmask );
sewardjde4a1d02002-03-22 01:27:54 +00001460
sewardj018f7622002-05-15 21:13:39 +00001461 /* Copy per-signal settings to SCSS. */
1462 for (i = 1; i <= VKI_KNSIG; i++) {
1463
1464 /* Get the old host action */
1465 ret = VG_(ksigaction)(i, NULL, &sa);
1466 vg_assert(ret == 0);
1467
1468 if (VG_(clo_trace_signals))
1469 VG_(printf)("snaffling handler 0x%x for signal %d\n",
1470 (Addr)(sa.ksa_handler), i );
1471
1472 vg_scss.scss_per_sig[i].scss_handler = sa.ksa_handler;
1473 vg_scss.scss_per_sig[i].scss_flags = sa.ksa_flags;
1474 vg_scss.scss_per_sig[i].scss_mask = sa.ksa_mask;
1475 vg_scss.scss_per_sig[i].scss_restorer = sa.ksa_restorer;
1476 }
1477
sewardj2342c972002-05-22 23:34:20 +00001478 /* Copy the alt stack, if any. */
1479 ret = VG_(ksigaltstack)(NULL, &vg_scss.altstack);
1480 vg_assert(ret == 0);
1481
sewardj018f7622002-05-15 21:13:39 +00001482 /* Copy the process' signal mask into the root thread. */
1483 vg_assert(VG_(threads)[1].status == VgTs_Runnable);
1484 VG_(threads)[1].sig_mask = saved_procmask;
1485
1486 /* Initialise DCSS. */
1487 for (i = 1; i <= VKI_KNSIG; i++) {
1488 vg_dcss.dcss_sigpending[i] = False;
1489 vg_dcss.dcss_destthread[i] = VG_INVALID_THREADID;
1490 }
1491
sewardjde4a1d02002-03-22 01:27:54 +00001492 /* Register an alternative stack for our own signal handler to run
1493 on. */
1494 altstack_info.ss_sp = &(VG_(sigstack)[0]);
1495 altstack_info.ss_size = 10000 * sizeof(UInt);
1496 altstack_info.ss_flags = 0;
1497 ret = VG_(ksigaltstack)(&altstack_info, NULL);
1498 if (ret != 0) {
njne427a662002-10-02 11:08:25 +00001499 VG_(core_panic)(
sewardjde4a1d02002-03-22 01:27:54 +00001500 "vg_sigstartup_actions: couldn't install alternative sigstack");
1501 }
1502 if (VG_(clo_trace_signals)) {
1503 VG_(message)(Vg_DebugExtraMsg,
1504 "vg_sigstartup_actions: sigstack installed ok");
1505 }
1506
sewardj7a61d912002-04-25 01:27:35 +00001507 /* DEBUGGING HACK */
1508 /* VG_(ksignal)(VKI_SIGUSR1, &VG_(oursignalhandler)); */
1509
sewardj018f7622002-05-15 21:13:39 +00001510 /* Calculate SKSS and apply it. This also sets the initial kernel
1511 mask we need to run with. */
1512 VG_(handle_SCSS_change)( True /* forced update */ );
sewardjde4a1d02002-03-22 01:27:54 +00001513}
1514
1515
1516/* Copy the process' sim signal state to the real state,
1517 for when we transfer from the simulated to real CPU.
1518 PROBLEM: what if we're running a signal handler when we
1519 get here? Hmm.
1520 I guess we wind up in vg_signalreturn_bogusRA, *or* the
1521 handler has done/will do a longjmp, in which case we're ok.
1522
1523 It is important (see vg_startup.S) that this proc does not
1524 change the state of the real FPU, since it is called when
1525 running the program on the real CPU.
1526*/
1527void VG_(sigshutdown_actions) ( void )
1528{
1529 Int i, ret;
1530
sewardjde4a1d02002-03-22 01:27:54 +00001531 vki_ksigset_t saved_procmask;
1532 vki_ksigaction sa;
1533
sewardj2e93c502002-04-12 11:12:52 +00001534 VG_(block_all_host_signals)( &saved_procmask );
sewardjde4a1d02002-03-22 01:27:54 +00001535
sewardj018f7622002-05-15 21:13:39 +00001536 /* Copy per-signal settings from SCSS. */
sewardjb48e5002002-05-13 00:16:03 +00001537 for (i = 1; i <= VKI_KNSIG; i++) {
sewardj018f7622002-05-15 21:13:39 +00001538
1539 sa.ksa_handler = vg_scss.scss_per_sig[i].scss_handler;
1540 sa.ksa_flags = vg_scss.scss_per_sig[i].scss_flags;
1541 sa.ksa_mask = vg_scss.scss_per_sig[i].scss_mask;
1542 sa.ksa_restorer = vg_scss.scss_per_sig[i].scss_restorer;
1543
1544 if (VG_(clo_trace_signals))
1545 VG_(printf)("restoring handler 0x%x for signal %d\n",
1546 (Addr)(sa.ksa_handler), i );
1547
sewardje8fb72e2002-06-28 02:08:28 +00001548 /* Set the old host action */
sewardj018f7622002-05-15 21:13:39 +00001549 ret = VG_(ksigaction)(i, &sa, NULL);
sewardje8fb72e2002-06-28 02:08:28 +00001550 if (i != VKI_SIGKILL && i != VKI_SIGSTOP)
1551 vg_assert(ret == 0);
sewardjde4a1d02002-03-22 01:27:54 +00001552 }
1553
sewardj2342c972002-05-22 23:34:20 +00001554 /* Restore the sig alt stack. */
1555 ret = VG_(ksigaltstack)(&vg_scss.altstack, NULL);
1556 vg_assert(ret == 0);
1557
sewardj018f7622002-05-15 21:13:39 +00001558 /* A bit of a kludge -- set the sigmask to that of the root
1559 thread. */
1560 vg_assert(VG_(threads)[1].status != VgTs_Empty);
1561 VG_(restore_all_host_signals)( &VG_(threads)[1].sig_mask );
sewardjde4a1d02002-03-22 01:27:54 +00001562}
1563
1564
sewardjde4a1d02002-03-22 01:27:54 +00001565/*--------------------------------------------------------------------*/
1566/*--- end vg_signals.c ---*/
1567/*--------------------------------------------------------------------*/