|
|
1.1 root 1: /*
2:
1.1.1.3 root 3: Copyright 1990,1991,1992 Eric R. Smith.
4:
1.1.1.4 ! root 5: Copyright 1992,1993 Atari Corporation.
1.1.1.3 root 6:
7: All rights reserved.
1.1 root 8:
9: */
10:
11:
12:
13: /* signal.c:: signal handling routines */
14:
15:
16:
17: #include "mint.h"
18:
19:
20:
21: void (*sig_routine)(); /* used in intr.s */
22:
1.1.1.2 root 23: short sig_exc; /* used in intr.s */
24:
1.1 root 25:
26:
27: /*
28:
29: * killgroup(pgrp, sig): send a signal to all members of a process group
30:
31: * returns 0 on success, or an error code on failure
32:
33: */
34:
35:
36:
37: long
38:
39: killgroup(pgrp, sig)
40:
41: int pgrp, sig;
42:
43: {
44:
45: PROC *p;
46:
47: int found = 0;
48:
49:
50:
1.1.1.2 root 51: TRACE(("killgroup %d %d", pgrp, sig));
1.1 root 52:
53:
54:
55: if (pgrp < 0)
56:
57: return EINTRN;
58:
59:
60:
61: for (p = proclist; p; p = p->gl_next) {
62:
63: if (p->pgrp == pgrp) {
64:
65: post_sig(p, sig);
66:
67: found++;
68:
69: }
70:
71: }
72:
73: if (found) {
74:
75: check_sigs(); /* see if the current process is affected */
76:
77: return 0;
78:
79: }
80:
81: else {
82:
1.1.1.2 root 83: DEBUG(("killgroup: no processes found"));
1.1 root 84:
85: return EFILNF;
86:
87: }
88:
89: }
90:
91:
92:
93: /* post_sig: post a signal as being pending. It is assumed that the
94:
95: caller has already verified that "sig" is a valid signal, and
96:
97: moreover it is the caller's responsibility to call check_sigs()
98:
99: if it's possible that p == curproc
100:
101: */
102:
103:
104:
105: void
106:
107: post_sig(p, sig)
108:
109: PROC *p;
110:
111: int sig;
112:
113: {
114:
115: ulong sigm;
116:
117:
118:
119: /* if process is ignoring this signal, do nothing
120:
121: * also: signal 0 is SIGNULL, and should never be delivered through
122:
123: * the normal channels (indeed, it's filtered out in dossig.c,
124:
125: * but the extra sanity check here is harmless). The kernel uses
126:
127: * signal 0 internally for some purposes, but it is handled
128:
129: * specially (see supexec() in xbios.c, for example).
130:
131: */
132:
133: if (p->sighandle[sig] == SIG_IGN || sig == 0)
134:
135: return;
136:
137:
138:
139: /* if the process is already dead, do nothing */
140:
141: if (p->wait_q == ZOMBIE_Q || p->wait_q == TSR_Q)
142:
143: return;
144:
145:
146:
147: /* mark the signal as pending */
148:
149: sigm = (1L << (unsigned long)sig);
150:
151: p->sigpending |= sigm;
152:
153:
154:
155: /* if the signal is masked, do nothing further */
156:
1.1.1.4 ! root 157: /* note: some signals can't be masked, and we handle those elsewhere so
! 158:
! 159: * that p->sigmask is always valid. SIGCONT is among the unmaskable
! 160:
! 161: * signals
! 162:
! 163: */
! 164:
1.1 root 165: if ( (p->sigmask & sigm) != 0 )
166:
167: return;
168:
169:
170:
171: /* otherwise, make sure the process is awake */
172:
173: if (p->wait_q && p->wait_q != READY_Q) {
174:
1.1.1.3 root 175: short sr = spl7();
176:
1.1.1.4 ! root 177: if (p->wait_q == SELECT_Q)
! 178:
! 179: p->wait_cond = 0;
! 180:
1.1 root 181: rm_q(p->wait_q, p);
182:
183: add_q(READY_Q, p);
184:
1.1.1.3 root 185: spl(sr);
186:
1.1 root 187: }
188:
189: }
190:
191:
192:
193: /*
194:
195: * check_sigs: see if we have any signals pending. if so,
196:
197: * handle them.
198:
199: */
200:
201:
202:
203: void
204:
205: check_sigs()
206:
207: {
208:
209: ulong sigs, sigm;
210:
1.1.1.2 root 211: int i;
212:
213: short deliversig;
1.1 root 214:
215:
216:
217: if (curproc->pid == 0) return;
218:
1.1.1.2 root 219: top:
220:
1.1 root 221: sigs = curproc->sigpending & ~(curproc->sigmask);
222:
223: if (sigs) {
224:
225: sigm = 2;
226:
1.1.1.2 root 227: /* with tracing we need a mechanism to allow a signal to be delivered
228:
229: * to the child (curproc); Fcntl(...TRACEGO...) passes a SIGNULL to indicate that we
230:
231: * should really deliver the signal, hence its always safe to remove it
232:
233: * from pending.
234:
235: */
236:
237: deliversig = (curproc->sigpending & 1L);
238:
239: curproc->sigpending &= ~1L;
240:
241:
242:
1.1 root 243: for (i = 1; i < NSIG; i++) {
244:
245: if (sigs & sigm) {
246:
1.1.1.2 root 247: curproc->sigpending &= ~sigm;
248:
1.1.1.4 ! root 249: if (curproc->ptracer && !deliversig &&
! 250:
! 251: i != SIGCONT) {
1.1 root 252:
1.1.1.2 root 253: TRACE(("tracer being notified of signal %d", i));
1.1 root 254:
1.1.1.2 root 255: stop(i);
1.1 root 256:
1.1.1.2 root 257: /* the parent may reset our pending signals, so check again */
258:
259: goto top;
260:
261: } else {
262:
263: ulong omask;
1.1 root 264:
265:
266:
1.1.1.2 root 267: curproc->sigpending &= ~sigm;
1.1 root 268:
1.1.1.2 root 269: omask = curproc->sigmask;
270:
271:
272:
273: /* sigextra gives which extra signals should also be masked */
274:
275: curproc->sigmask |= curproc->sigextra[i] | sigm;
276:
277: handle_sig(i);
1.1 root 278:
279:
280:
281:
282:
283: /*
284:
285: * POSIX.1-3.3.4.2(723) "If and when the user's signal handler returns
286:
287: * normally, the original signal mask is restored."
288:
289: *
290:
291: * BUG?: This unmasking could unmask a pending signal which we will not
292:
293: * see this time around (if the signal number is less than i) and which
294:
295: * was not pending when we started; should we detect this condition and
296:
297: * loop around for a second try? POSIX only guarantees delivery of
298:
299: * one signal per kernel entry, so this shouldn't really be a problem.
300:
301: */
302:
1.1.1.2 root 303: curproc->sigmask = omask; /* unmask signals */
304:
305: }
1.1 root 306:
307: }
308:
309: sigm = sigm << 1;
310:
311: }
312:
313: }
314:
315: }
316:
317:
318:
319: /*
320:
321: * raise: cause a signal to be raised in the current process
322:
323: */
324:
325:
326:
327: void
328:
329: raise(sig)
330:
331: int sig;
332:
333: {
334:
335: post_sig(curproc, sig);
336:
337: check_sigs();
338:
339: }
340:
341:
342:
343: #ifdef EXCEPTION_SIGS
344:
345: /* exception numbers corresponding to signals */
346:
347: char excep_num[NSIG] =
348:
349: { 0, 0, 0, 0,
350:
351: 4, /* SIGILL == illegal instruction */
352:
353: 9, /* SIGTRAP == trace trap */
354:
355: 4, /* pretend SIGABRT is also illegal instruction */
356:
357: 8, /* SIGPRIV == privileged instruction exception */
358:
359: 5, /* SIGFPE == divide by zero */
360:
361: 0, 2, /* SIGBUS == bus error */
362:
363: 3 /* SIGSEGV == address error */
364:
365: /* everything else gets zeros */
366:
367: };
368:
369:
370:
371: /* a "0" means we don't print a message when it happens -- typically the
372:
373: user is expecting a synchronous signal, so we don't need to report it
374:
375: */
376:
377:
378:
379: const char *signames[NSIG] = { 0,
380:
381: 0, 0, 0, "ILLEGAL INSTRUCTION", "TRACE TRAP",
382:
383: 0, "PRIVILEGE VIOLATION", "DIVISION BY ZERO", 0, "BUS ERROR",
384:
385: "ADDRESS ERROR", "BAD SYSTEM CALL", 0, 0, 0,
386:
387: 0, 0, 0, 0, 0,
388:
389: 0, 0, 0, "CPU TIME EXHAUSTED", "FILE TOO BIG",
390:
391: 0, 0, 0, 0, 0
392:
393: };
394:
395:
396:
397: /*
398:
399: * replaces the TOS "show bombs" routine: for now, print the name of the
400:
401: * interrupt on the console, and save info on the crash in the appropriate
402:
403: * system area
404:
405: */
406:
407:
408:
409: void
410:
411: bombs(sig)
412:
413: int sig;
414:
415: {
416:
417: long *procinfo = (long *)0x380L;
418:
419: int i;
420:
421: CONTEXT *crash;
422:
1.1.1.3 root 423: extern int no_mem_prot;
424:
425:
426:
427: if (sig < 0 || sig > 31) {
428:
429: ALERT("bombs(%d): sig out of range", sig);
430:
431: }
432:
433: else if (signames[sig]) {
1.1 root 434:
1.1.1.3 root 435: if (!no_mem_prot && sig == SIGBUS) {
1.1 root 436:
1.1.1.3 root 437: /* already reported by report_buserr */
1.1 root 438:
1.1.1.3 root 439: } else {
1.1 root 440:
1.1.1.3 root 441: ALERT("%s: User PC=%lx (basepage=%lx)",
1.1 root 442:
1.1.1.3 root 443: signames[sig],
1.1 root 444:
1.1.1.3 root 445: curproc->exception_pc, curproc->base);
1.1 root 446:
1.1.1.3 root 447: }
1.1 root 448:
449: /* save the processor state at crash time */
450:
451: /* assumes that "crash time" is the context curproc->ctxt[SYSCALL] */
452:
453: /* BUG: this is not true if the crash happened in the kernel; in the
454:
455: * latter case, the crash context wasn't saved anywhere.
456:
457: */
458:
459: crash = &curproc->ctxt[SYSCALL];
460:
1.1.1.2 root 461: *procinfo++ = 0x12345678L; /* magic flag for valid info */
1.1 root 462:
463: for (i = 0; i < 15; i++)
464:
465: *procinfo++ = crash->regs[i];
466:
1.1.1.3 root 467: *procinfo++ = curproc->exception_ssp;
1.1 root 468:
469: *procinfo++ = ((long)excep_num[sig]) << 24L;
470:
1.1.1.2 root 471: *procinfo = crash->usp;
1.1 root 472:
473:
474:
475: /* we're also supposed to save some info from the supervisor stack. it's not
476:
477: * clear what we should do for MiNT, since most of the stuff that used to be
478:
479: * on the stack has been put in the CONTXT struct. Moreover, we don't want
480:
481: * to crash because of an attempt to access illegal memory. Hence, we do
482:
483: * nothing here...
484:
485: */
486:
1.1.1.3 root 487: } else {
488:
489: TRACE(("bombs(%d)", sig));
490:
1.1 root 491: }
492:
493: }
494:
495: #endif
496:
497:
498:
499: /*
500:
501: * handle_sig: do whatever is appropriate to handle a signal
502:
503: */
504:
505:
506:
507: static long unwound_stack = 0;
508:
509:
510:
511: void
512:
513: handle_sig(sig)
514:
515: int sig;
516:
517: {
518:
519: long oldstack, newstack;
520:
521: long *stack;
522:
1.1.1.4 ! root 523: CONTEXT *call, contexts[2];
! 524:
! 525: #define oldsysctxt (contexts[0])
! 526:
! 527: #define newcurrent (contexts[1])
! 528:
! 529:
1.1 root 530:
531: extern void sig_return();
532:
533:
534:
535: if (curproc->sighandle[sig] == SIG_IGN)
536:
537: return;
538:
539: else if (curproc->sighandle[sig] == SIG_DFL) {
540:
541: _default:
542:
543: switch(sig) {
544:
545: #if 0
546:
547: /* Note: SIGNULL is filtered out in dossig.c and is never actually
548:
549: * delivered (its only purpose for the user is to test for the existence of
550:
551: * a process, it isn't a real signal). The kernel uses SIGNULL
552:
553: * internally, but all such code does the signal handling "by hand"
554:
555: * and so no default handling is necessary.
556:
557: */
558:
1.1.1.2 root 559: case SIGNULL:
1.1 root 560:
561: #endif
562:
1.1.1.2 root 563: case SIGWINCH:
1.1 root 564:
1.1.1.2 root 565: case SIGCHLD:
1.1 root 566:
1.1.1.3 root 567: /* SIGFPE is divide by 0; TOS ignores this, so we will too */
568:
569: case SIGFPE:
570:
1.1.1.2 root 571: return; /* do nothing */
1.1 root 572:
1.1.1.2 root 573: case SIGSTOP:
1.1 root 574:
1.1.1.2 root 575: case SIGTSTP:
1.1 root 576:
1.1.1.2 root 577: case SIGTTIN:
1.1 root 578:
1.1.1.2 root 579: case SIGTTOU:
1.1 root 580:
1.1.1.2 root 581: stop(sig);
1.1 root 582:
1.1.1.2 root 583: return;
1.1 root 584:
1.1.1.2 root 585: case SIGCONT:
1.1 root 586:
1.1.1.2 root 587: curproc->sigpending &= ~STOPSIGS;
1.1 root 588:
1.1.1.2 root 589: return;
1.1 root 590:
591:
592:
1.1.1.2 root 593: /* here are the fatal signals. for SIGINT, we use p_term(-32) so that
1.1 root 594:
1.1.1.2 root 595: * TOS programs that catch ^C via the vector at 0x400 and which expect
1.1 root 596:
1.1.1.2 root 597: * TOS's error code (-32) to be sent will work. For most other signals,
1.1 root 598:
1.1.1.2 root 599: * we p_term with an error code; for SIGKILL, we don't want to allow
1.1 root 600:
1.1.1.2 root 601: * the program any chance to recover, so we call terminate() directly
1.1 root 602:
1.1.1.2 root 603: * to avoid calling through to the user's terminate vector.
1.1 root 604:
1.1.1.2 root 605: */
1.1 root 606:
1.1.1.2 root 607: case SIGINT: /* ^C */
1.1 root 608:
1.1.1.2 root 609: if (curproc->domain == DOM_TOS) {
1.1 root 610:
1.1.1.2 root 611: p_term(-32);
1.1 root 612:
1.1.1.2 root 613: return;
1.1 root 614:
1.1.1.2 root 615: }
616:
617: /* otherwise, fall through */
1.1 root 618:
1.1.1.2 root 619: default:
1.1 root 620:
621: #ifdef EXCEPTION_SIGS
622:
1.1.1.2 root 623: bombs(sig); /* tell the user what happened */
1.1 root 624:
625: #endif
626:
1.1.1.2 root 627: /* the "sigmask" check is in case a bus error happens in the user's
628:
629: * term_vec code; we don't want to get stuck in an infinite loop!
630:
631: */
632:
633: if ((curproc->sigmask & 1L) || sig == SIGKILL)
634:
1.1 root 635: terminate(sig << 8, ZOMBIE_Q);
636:
1.1.1.2 root 637: else
638:
639: p_term(sig << 8);
640:
1.1 root 641: }
642:
643: }
644:
645: else { /* user wants to handle it himself */
646:
647:
648:
649: /* another kludge: there is one case in which the p_sigreturn mechanism
650:
651: * is invoked by the kernel, namely when the user calls Supexec()
652:
653: * or when s/he installs a handler for the GEMDOS terminate vector (#0x102)
654:
655: * and the program terminates. MiNT fakes the call to user code with
656:
657: * signal 0 (SIGNULL); programs that longjmp out of the user function
658:
659: * and are later sent back to it again (e.g. if ^C keeps getting pressed
660:
661: * and a terminate vector has been installed) will grow the stack without
662:
663: * bound unless we watch for this case.
664:
665: *
666:
667: * Solution (sort of): whenever Pterm() is called, we unwind the
668:
669: * stack; otherwise, we let it grow, so that nested Supexec()
670:
671: * calls work.
672:
673: *
674:
675: * Note that SIGNULL is thrown away when sent by user processes,
676:
677: * and the user can't mask it (it's UNMASKABLE), so there is
678:
679: * is no possibility of confusion with anything the user does.
680:
681: */
682:
683: if (sig == 0) {
684:
685: /* p_term() sets sigmask to let us know to do Psigreturn */
686:
687: if (curproc->sigmask & 1L) {
688:
689: p_sigreturn();
690:
691: curproc->sigmask &= ~1L;
692:
693: } else {
694:
695: unwound_stack = 0;
696:
697: }
698:
699: }
700:
701:
702:
703: call = &curproc->ctxt[SYSCALL];
704:
705: /*
706:
707: * what we do is build two fake stack frames; the bottom one is
708:
709: * for a call to the user function, with (long)parameter being the
710:
711: * signal number; the top one is for sig_return.
712:
713: * When the user function returns, it returns to sig_return, which
714:
715: * calls into the kernel to restore the context in prev_ctxt
716:
717: * (thus putting us back here). We can then continue on our way.
718:
719: */
720:
721:
722:
723: /* set a new system stack, with a bit of buffer space */
724:
725: oldstack = curproc->sysstack;
726:
1.1.1.4 ! root 727: newstack = ((long) ( (&newcurrent) - 2 )) - 12;
1.1 root 728:
729:
730:
731: if (newstack < (long)curproc->stack + ISTKSIZE + 256) {
732:
733: ALERT("stack overflow");
734:
735: goto _default;
736:
737: }
738:
739: else if ((long) curproc->stack + STKSIZE < newstack) {
740:
741: FATAL("system stack not in proc structure");
742:
743: }
744:
745:
746:
747: /* unwound_stack is set by p_sigreturn() */
748:
749: if (sig == 0 && unwound_stack)
750:
751: curproc->sysstack = unwound_stack;
752:
753: else
754:
755: curproc->sysstack = newstack;
756:
757: oldsysctxt = *call;
758:
759: stack = (long *)(call->sr & 0x2000 ? call->ssp :
760:
761: call->usp);
762:
763: /*
764:
765: Hmmm... here's another potential problem for the signal 0 terminate
766:
767: vector: if the program keeps returning back to user mode without
768:
769: worrying about the supervisor stack, we'll eventually overflow it.
770:
771: However, if the program is in supervisor mode itself, then we don't
772:
773: want to stomp on its stack. Temporary solution: ignore the problem,
774:
1.1.1.2 root 775: the stack's only growing 12 bytes at a time.
1.1 root 776:
777: */
778:
1.1.1.2 root 779: /*
780:
781: * in addition to the signal number we stuff the vector offset on the
782:
783: * stack; if the user is interested they can sniff it, if not ignoring
784:
785: * it needs no action on their part. Why do we need this? So that a
786:
787: * single SIGFPE handler (for example) can discriminate amongst the
788:
789: * multiple things which may get thrown its way
790:
791: */
792:
793: *(--stack) = (long)call->sfmt & 0xfff;
794:
1.1 root 795: *(--stack) = (long)sig;
796:
797: *(--stack) = (long)sig_return;
798:
799: if (call->sr & 0x2000)
800:
801: call->ssp = ((long) stack);
802:
803: else
804:
805: call->usp = ((long) stack);
806:
807: call->pc = (long) curproc->sighandle[sig];
808:
1.1.1.2 root 809: call->sfmt = call->fstate[0] = 0; /* don't restart FPU communication */
810:
1.1 root 811:
812:
813: ((long *)curproc->sysstack)[1] = FRAME_MAGIC;
814:
815: ((long *)curproc->sysstack)[2] = oldstack;
816:
817: ((long *)curproc->sysstack)[3] = sig;
818:
819:
820:
1.1.1.2 root 821: if (curproc->sigflags[sig] & SA_RESET) {
822:
823: curproc->sighandle[sig] = SIG_DFL;
824:
825: curproc->sigflags[sig] &= ~SA_RESET;
826:
827: }
828:
829:
830:
1.1 root 831: if (save_context(&newcurrent) == 0 ) {
832:
833: /*
834:
835: * go do the signal; eventually, we'll restore this context (unless the
836:
837: * user longjmp'd out of his signal handler). while the user is handling
838:
839: * the signal, it's masked out to prevent race conditions. p_sigreturn()
840:
841: * will unmask it for us when the user is finished.
842:
843: */
844:
845: newcurrent.regs[0] = CTXT_MAGIC;
846:
847: /* set D0 so next return is different */
848:
849: assert(curproc->magic == CTXT_MAGIC);
850:
851: leave_kernel();
852:
853: restore_context(call);
854:
855: }
856:
857: /*
858:
859: * OK, we get here from p_sigreturn, via the user returning from
860:
861: * the handler to sig_return. Restoring the stack and unmasking the
862:
863: * signal have been done already for us by p_sigreturn.
864:
865: * We should just restore the old system call context
866:
867: * and continue with whatever it was we were doing.
868:
869: */
870:
1.1.1.2 root 871: TRACE(("done handling signal"));
1.1 root 872:
873: curproc->ctxt[SYSCALL] = oldsysctxt;
874:
875: assert(curproc->magic == CTXT_MAGIC);
876:
877: }
878:
1.1.1.4 ! root 879: #undef oldsysctxt
! 880:
! 881: #undef newcurrent
! 882:
1.1 root 883: }
884:
885:
886:
887: /*
888:
889: * the p_sigreturn system call
890:
891: * When called by the user from inside a signal handler, it indicates a
892:
893: * desire to restore the old stack frame prior to a longjmp() out of
894:
895: * the handler.
896:
897: * When called from the sig_return module, it indicates that the user
898:
899: * is finished a handler, and we should not only restore the stack
900:
901: * frame but also the old context we were working in (which is on the
902:
903: * system call stack -- see handle_sig).
904:
905: * The "valid_return" variable is 0 in the first case, 1 in the second.
906:
907: */
908:
909:
910:
911: short valid_return;
912:
913:
914:
1.1.1.2 root 915: long ARGS_ON_STACK
1.1 root 916:
917: p_sigreturn()
918:
919: {
920:
921: CONTEXT *oldctxt;
922:
923: long *frame;
924:
925: long sig;
926:
927:
928:
929: unwound_stack = 0;
930:
931: top:
932:
933: frame = (long *)curproc->sysstack;
934:
935: frame++; /* frame should point at FRAME_MAGIC, now */
936:
937: sig = frame[2];
938:
939: if (*frame != FRAME_MAGIC || (sig < 0) || (sig >= NSIG)) {
940:
941: FATAL("Psigreturn: system stack corrupted");
942:
943: }
944:
945: if (frame[1] == 0) {
946:
1.1.1.2 root 947: DEBUG(("Psigreturn: frame at %lx points to 0", frame-1));
1.1 root 948:
949: return 0;
950:
951: }
952:
953: unwound_stack = curproc->sysstack;
954:
1.1.1.2 root 955: TRACE(("Psigreturn(%d)", (int)sig));
1.1 root 956:
957:
958:
959: curproc->sysstack = frame[1]; /* restore frame */
960:
961: curproc->sigmask &= ~(1L<<sig); /* unblock signal */
962:
963:
964:
965: if (!valid_return) {
966:
967: /* here, the user is telling us that a longjmp out of a signal handler is
968:
969: * about to occur; so we should unwind *all* the signal frames
970:
971: */
972:
973: goto top;
974:
975: }
976:
977: else {
978:
979: valid_return = 0;
980:
1.1.1.4 ! root 981: oldctxt = ((CONTEXT *)(&frame[2])) + 2;
1.1 root 982:
983: if (oldctxt->regs[0] != CTXT_MAGIC) {
984:
985: FATAL("p_sigreturn: corrupted context");
986:
987: }
988:
989: assert(curproc->magic == CTXT_MAGIC);
990:
991: restore_context(oldctxt);
992:
993: return 0; /* dummy -- this isn't reached */
994:
995: }
996:
997: }
998:
999:
1000:
1001: /*
1002:
1003: * stop a process because of signal "sig"
1004:
1005: */
1006:
1007:
1008:
1009: void
1010:
1011: stop(sig)
1012:
1013: int sig;
1014:
1015: {
1016:
1017: unsigned int code;
1018:
1019: unsigned long oldmask;
1020:
1021: PROC *p;
1022:
1023:
1024:
1025: code = sig << 8;
1026:
1027:
1028:
1029: if (curproc->pid == 0) {
1030:
1.1.1.3 root 1031: FORCE("attempt to stop MiNT");
1.1 root 1032:
1033: return;
1034:
1035: }
1036:
1037:
1038:
1039: /* notify parent */
1040:
1.1.1.2 root 1041: if (curproc->ptracer) {
1.1 root 1042:
1.1.1.2 root 1043: p = curproc->ptracer;
1.1 root 1044:
1045: post_sig(p, SIGCHLD);
1046:
1.1.1.2 root 1047: } else {
1048:
1049: p = pid2proc(curproc->ppid);
1050:
1051: if (p && !(p->sigflags[SIGCHLD] & SA_NOCLDSTOP))
1052:
1053: post_sig(p, SIGCHLD);
1054:
1.1 root 1055: }
1056:
1057:
1058:
1059: oldmask = curproc->sigmask;
1060:
1061:
1062:
1.1.1.2 root 1063: if ((1L << sig) & STOPSIGS) {
1064:
1065: /* mask out most signals */
1066:
1067: curproc->sigmask |= ~(UNMASKABLE | SIGTERM);
1068:
1069: }
1.1 root 1070:
1.1.1.2 root 1071: else
1072:
1073: assert(curproc->ptracer);
1.1 root 1074:
1075:
1076:
1077: /* sleep until someone signals us awake */
1078:
1079: sleep(STOP_Q, (long) code | 0177);
1080:
1081:
1082:
1083: /* when we wake up, restore the signal mask */
1084:
1085: curproc->sigmask = oldmask;
1086:
1087:
1088:
1089: /* and discard any signals that would cause us to stop again */
1090:
1091: curproc->sigpending &= ~STOPSIGS;
1092:
1093: }
1094:
1095:
1096:
1097: /*
1098:
1099: * interrupt handlers to raise SIGBUS, SIGSEGV, etc. Note that for
1100:
1101: * really fatal errors we reset the handler to SIG_DFL, so that
1102:
1103: * a second such error kills us
1104:
1105: */
1106:
1107:
1108:
1109: void
1110:
1111: exception(sig)
1112:
1113: int sig;
1114:
1115: {
1116:
1.1.1.2 root 1117: curproc->sigflags[sig] |= SA_RESET;
1118:
1.1.1.3 root 1119: DEBUG(("exception #%d raised", sig));
1.1 root 1120:
1121: raise(sig);
1122:
1123: }
1124:
1125:
1126:
1127: void
1128:
1129: sigbus()
1130:
1131: {
1132:
1.1.1.4 ! root 1133: if (curproc->sighandle[SIGBUS] == SIG_DFL)
! 1134:
! 1135: report_buserr();
1.1.1.3 root 1136:
1.1 root 1137: exception(SIGBUS);
1138:
1139: }
1140:
1141:
1142:
1143: void
1144:
1145: sigaddr()
1146:
1147: {
1148:
1149: exception(SIGSEGV);
1150:
1151: }
1152:
1153:
1154:
1155: void
1156:
1157: sigill()
1158:
1159: {
1160:
1161: exception(SIGILL);
1162:
1163: }
1164:
1165:
1166:
1167: void
1168:
1169: sigpriv()
1170:
1171: {
1172:
1173: raise(SIGPRIV);
1174:
1175: }
1176:
1177:
1178:
1179: void
1180:
1181: sigfpe()
1182:
1183: {
1184:
1.1.1.2 root 1185: extern short fpu; /* in main.c */
1186:
1187:
1188:
1189: if (fpu) {
1190:
1191: CONTEXT *ctxt;
1192:
1193:
1194:
1195: ctxt = &curproc->ctxt[SYSCALL];
1196:
1197:
1198:
1199: /* 0x1f38 is a Motorola magic cookie to detect a 68882 idle state frame */
1200:
1201: if (*(ushort *)ctxt->fstate == 0x1f38 &&
1202:
1203: (ctxt->sfmt & 0xfff) >= 0xc0L && (ctxt->sfmt & 0xfff) <= 0xd8L) {
1204:
1205: /* fix a bug in the 68882 - Motorola call it a feature :-) */
1206:
1207: ctxt->fstate[ctxt->fstate[1]] |= 1 << 3;
1208:
1209: }
1210:
1211: }
1212:
1.1 root 1213: raise(SIGFPE);
1214:
1215: }
1216:
1217:
1218:
1219: void
1220:
1221: sigtrap()
1222:
1223: {
1224:
1225: raise(SIGTRAP);
1226:
1227: }
1228:
1.1.1.2 root 1229:
1230:
1231: void
1232:
1233: haltformat()
1234:
1235: {
1236:
1237: FATAL("halt: invalid stack frame format");
1238:
1239: }
1240:
1241:
1242:
1243: void
1244:
1245: haltcpv()
1246:
1247: {
1248:
1249: FATAL("halt: coprocessor protocol violation");
1250:
1251: }
1252:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.