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