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