Copyright (C) 1994, Digital Equipment Corp.
UNSAFE MODULE; IMPORT 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 RTSignal 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; PROCEDURESetHandler (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, new, initial_handlers[id]); IF (initial_handlers[id].sa_handler # DefaultHandler) THEN (* don't override inherited, non-default handlers *) EVAL Usignal.sigaction (sig, initial_handlers[id], new); END; END SetHandler; PROCEDURERestoreHandlers () = 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; PROCEDURERestoreHandler (id: INTEGER; sig: int) = VAR old: Usignal.struct_sigaction; BEGIN EVAL Usignal.sigaction (sig, initial_handlers[id], old); END RestoreHandler; PROCEDUREShutdown (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, new, old); (* restore default handler *) EVAL Usignal.kill (Uprocess.getpid (), sig); (* and resend the signal *) END Shutdown; PROCEDUREInterrupt (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; PROCEDUREQuit (<*UNUSED*> sig, code: int; <*UNUSED*>scp: SigInfo) = VAR pc := 0; BEGIN (*IF (scp # NIL) THEN pc := scp.sc_pc END;*) RTMisc.FatalErrorPC (pc, "aborted"); END Quit; PROCEDURESegV (<*UNUSED*> sig, code: int; <*UNUSED*>scp: SigInfo) = VAR pc := 0; BEGIN (*IF (scp # NIL) THEN pc := scp.sc_pc END;*) RTMisc.FatalErrorPC (pc, "Segmentation violation - possible attempt to dereference NIL"); END SegV; BEGIN END RTSignal.