m3core/src/runtime/FreeBSD3/RTSignal.m3


 Copyright (C) 1992, Digital Equipment Corporation          
 All rights reserved.                                       
 See the file COPYRIGHT for a full description.             
                                                            
 Last modified on Mon Nov 21 10:31:19 PST 1994 by kalsow    
      modified on Mon Mar 16 18:10:15 PST 1992 by muller    

UNSAFE MODULE RTSignal;

IMPORT RTError, (* RTMisc, *) RTProcess, Usignal, Uprocess;
FROM Ctypes IMPORT int;

TYPE
  SigInfo = UNTRACED REF Usignal.struct_sigcontext;

VAR
  DefaultHandler   : Usignal.SignalHandler;
  IgnoreSignal     : Usignal.SignalHandler;
  initial_handlers : ARRAY [0..5] OF Usignal.struct_sigaction;

PROCEDURE InstallHandlers () =
  BEGIN
    DefaultHandler := LOOPHOLE (0, Usignal.SignalHandler);
    IgnoreSignal   := LOOPHOLE (1, Usignal.SignalHandler);

    SetHandler (0, Usignal.SIGHUP,  Shutdown);
    SetHandler (1, Usignal.SIGINT,  Interrupt);
    SetHandler (2, Usignal.SIGQUIT, Quit);
    SetHandler (3, Usignal.SIGSEGV, SegV);
    SetHandler (4, Usignal.SIGPIPE, IgnoreSignal);
    SetHandler (5, Usignal.SIGTERM, Shutdown);
  END InstallHandlers;

PROCEDURE SetHandler (id: INTEGER; sig: int;  handler: Usignal.SignalHandler) =
  (* Note: we use the LOOPHOLE to prevent the runtime check for
     nested procedure.  The runtime check crashes when
     handler = IgnoreSignal = 1. *)
  VAR new: Usignal.struct_sigaction;
  BEGIN
    new.sa_handler := LOOPHOLE (handler, Usignal.SignalHandler);
    new.sa_flags   := 0;
    EVAL Usignal.sigaction (sig, ADR(new), ADR(initial_handlers[id]));
    IF (initial_handlers[id].sa_handler # DefaultHandler) THEN
      (* don't override inherited, non-default handlers *)
      EVAL Usignal.sigaction (sig, ADR(initial_handlers[id]), ADR(new));
    END;
  END SetHandler;

PROCEDURE RestoreHandlers () =
  BEGIN
    RestoreHandler (0, Usignal.SIGHUP);
    RestoreHandler (1, Usignal.SIGINT);
    RestoreHandler (2, Usignal.SIGQUIT);
    RestoreHandler (3, Usignal.SIGSEGV);
    RestoreHandler (4, Usignal.SIGPIPE);
    RestoreHandler (5, Usignal.SIGTERM);
  END RestoreHandlers;

PROCEDURE RestoreHandler (id: INTEGER;  sig: int) =
  BEGIN
    EVAL Usignal.sigaction (sig, ADR(initial_handlers[id]), NIL);
  END RestoreHandler;

PROCEDURE Shutdown (sig: int; <*UNUSED*> code: int; <*UNUSED*> scp: SigInfo) =
  VAR new, old: Usignal.struct_sigaction;
  BEGIN
    new.sa_handler := DefaultHandler;
    new.sa_flags   := 0;
    RTProcess.InvokeExitors ();                   (* flush stdio... *)
    EVAL Usignal.sigaction (sig, ADR(new), ADR(old));       (* restore default handler *)
    EVAL Usignal.kill (Uprocess.getpid (), sig);  (* and resend the signal *)
  END Shutdown;

PROCEDURE Interrupt (sig: int;  code: int;  scp: SigInfo) =
  VAR h := RTProcess.OnInterrupt (NIL);
  BEGIN
    IF (h = NIL) THEN
      Shutdown (sig, code, scp);
    ELSE
      EVAL RTProcess.OnInterrupt (h); (* reinstall the handler *)
      h ();
    END;
  END Interrupt;

PROCEDURE Quit (<*UNUSED*> sig, code: int; scp: SigInfo) =
  VAR pc := 0;
  BEGIN
    IF (scp # NIL) THEN pc := scp.sc_eip END;
    RTError.Msg (NIL, 0, "aborted");
    (* RTMisc.FatalErrorPC (pc, "aborted"); *)
  END Quit;

PROCEDURE SegV (<*UNUSED*> sig, code: int; scp: SigInfo) =
  VAR pc := 0;
  BEGIN
    IF (scp # NIL) THEN pc := scp.sc_eip END;
    RTError.Msg (NIL, 0,
      "Segmentation violation - possible attempt to dereference NIL");
    (* RTMisc.FatalErrorPC (pc,
      "Segmentation violation - possible attempt to dereference NIL"); *)
  END SegV;

BEGIN
END RTSignal.