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