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