copied from LINUXLIBC6
UNSAFE MODULE; IMPORT RTError, RTProcess, Usignal, Uprocess, Uucontext; FROM Ctypes IMPORT int; VAR DefaultHandler : Usignal.SignalActionHandler; IgnoreSignal : Usignal.SignalActionHandler; initial_handlers : ARRAY [0..5] OF Usignal.struct_sigaction; PROCEDURE RTSignal InstallHandlers () = BEGIN DefaultHandler := LOOPHOLE (0, Usignal.SignalActionHandler); IgnoreSignal := LOOPHOLE (1, Usignal.SignalActionHandler); (* Note: we cannot use Usignal.SIG_DFL and Usignal.SIG_IGN because they may not be initialized when this module is kicked into action by the low-level runtime startup code... *) 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.SignalActionHandler) = VAR new: Usignal.struct_sigaction; BEGIN new.sa_sigaction := LOOPHOLE (handler, Usignal.SignalActionHandler); new.sa_flags := Usignal.SA_SIGINFO; WITH i = Usignal.sigemptyset(new.sa_mask) DO <*ASSERT i = 0*> END; WITH i = Usignal.sigaction (sig, new, initial_handlers[id]) DO <*ASSERT i = 0*> END; IF (initial_handlers[id].sa_sigaction # DefaultHandler) THEN (* don't override inherited, non-default handlers *) WITH i = Usignal.sigaction (sig, initial_handlers[id], new) DO <*ASSERT i = 0*> END; 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*> sip: Usignal.siginfo_t_star; <*UNUSED*> uap: Uucontext.ucontext_t_star) = VAR new, old: Usignal.struct_sigaction; BEGIN new.sa_sigaction := DefaultHandler; new.sa_flags := 0; EVAL Usignal.sigemptyset(new.sa_mask); RTProcess.InvokeExitors (); (* flush stdio... *) (* restore default handler *) EVAL Usignal.sigaction (sig, new, old); EVAL Usignal.kill (Uprocess.getpid (), sig); (* and resend the signal *) END Shutdown; PROCEDUREInterrupt (sig: int; sip: Usignal.siginfo_t_star; uap: Uucontext.ucontext_t_star) = VAR h := RTProcess.OnInterrupt (NIL); BEGIN IF (h = NIL) THEN Shutdown (sig, sip, uap); ELSE EVAL RTProcess.OnInterrupt (h); (* reinstall the handler *) h (); END; END Interrupt; PROCEDUREQuit (<*UNUSED*> sig: int; <*UNUSED*> sip: Usignal.siginfo_t_star; <*UNUSED*> uap: Uucontext.ucontext_t_star) = VAR pc := 0; BEGIN (* IF (uap # NIL) THEN pc := uap.uc_mcontext.gregs[Uucontext.REG_EIP]; END; *) (* If we must get the program counter, defer to #ifdef'ed C code. *) RTError.MsgPC (pc, "aborted"); END Quit; PROCEDURESegV (<*UNUSED*> sig: int; <*UNUSED*> sip: Usignal.siginfo_t_star; <*UNUSED*> uap: Uucontext.ucontext_t_star) = VAR pc := 0; BEGIN (* IF (uap # NIL) THEN pc := uap.uc_mcontext.gregs[Uucontext.REG_EIP]; END; *) (* If we must get the program counter, defer to #ifdef'ed C code. *) RTError.MsgPC (pc, "Segmentation violation - possible attempt to dereference NIL"); END SegV; BEGIN END RTSignal.