r11464: add signal handling functions
[kmrcl.git] / signals.lisp
1 ;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Base: 10; Package: modlisp -*-
2 ;;;; *************************************************************************
3 ;;;; FILE IDENTIFICATION
4 ;;;;
5 ;;;; Name:          signals.lisp
6 ;;;; Purpose:       Signal processing functions
7 ;;;; Programmer:    Kevin M. Rosenberg
8 ;;;; Date Started:  Jan 2007
9 ;;;;
10 ;;;; $Id: processes.lisp 10985 2006-07-26 18:52:03Z kevin $
11 ;;;; *************************************************************************
12
13 (in-package #:kmrcl)
14
15 (defun signal-key-to-number (sig)
16   "These signals and numbers are only valid on POSIX systems, perhaps
17 some are Linux-specific."
18   (case sig
19     (:hup 1)
20     (:int 2)
21     (:quit 3)
22     (:kill 9)
23     (:usr1 10)
24     (:usr2 12)
25     (:pipe 13)
26     (:alrm 14)
27     (:term 15)
28     (t
29      (error "Signal ~A not known." sig))))
30
31
32 (defun set-signal-handler (sig handler)
33   "Sets the handler for a signal to a function. Where possible, returns
34 the old handler for the function for later restoration with remove-signal-handler
35 below.
36
37 To be portable, signal handlers should use (&rest dummy) function signatures
38 and ignore the value. They should return T to tell some Lisp implementations (Allegro)
39 that the signal was successfully handled."
40   (let ((signum (etypecase sig
41                   (integer sig)
42                   (keyword (signal-key-to-number sig)))))
43     #+allegro (excl:add-signal-handler signum handler)
44     #+cmu (system:enable-interrupt signum handler)
45     #+lispworks
46     ;; non-documented method to get old handler, works in lispworks 5
47     (let ((old-handler (when (and (boundp 'system::*signal-handler-functions*)
48                                   (typep system::*signal-handler-functions* 'array))
49                          (aref system::*signal-handler-functions* signum))))
50       (system:set-signal-handler signum handler)
51       old-handler)
52     #+sbcl (sb-sys:enable-interrupt signum handler)
53     #-(or allegro cmu lispworks sbcl) (warn "Signal setting not supported on this platform.")
54   ))
55
56 (defun remove-signal-handler (sig &optional old-handler)
57   "Removes a handler from signal. Tries, when possible, to restore old-handler."
58   (let ((signum (etypecase sig
59                   (integer sig)
60                   (keyword (signal-key-to-number sig)))))
61     ;; allegro automatically restores old handler, because set-signal-handler above
62     ;; actually pushes the new handler onto a list of handlers
63     #+allegro (declare (ignore old-handler))
64     #+allegro (excl:remove-signal-handler signum)
65     #+cmu (system:enable-interrupt signum (or old-handler :default))
66     ;; lispworks removes handler if old-handler is nil
67     #+lispworks (system:set-signal-handler signum old-handler)
68     #+sbcl (sb-sys:enable-interrupt signum (or old-handler :default))
69     #-(or allegro cmu lispworks sbcl) (warn "Signal setting not supported on this platform.")
70     ))