0.8.4.30:
[sbcl.git] / src / code / target-signal.lisp
1 ;;;; code for handling UNIX signals
2
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
11
12 (in-package "SB!UNIX")
13
14 ;;; These should probably be somewhere, but I don't know where.
15 (defconstant sig_dfl 0)
16 (defconstant sig_ign 1)
17 \f
18 ;;;; system calls that deal with signals
19
20 #!-sb-fluid (declaim (inline real-unix-kill))
21 (sb!alien:define-alien-routine ("kill" real-unix-kill) sb!alien:int
22   (pid sb!alien:int)
23   (signal sb!alien:int))
24
25 ;;; Send the signal SIGNAL to the process with process id PID. SIGNAL
26 ;;; should be a valid signal number
27 (defun unix-kill (pid signal)
28   (real-unix-kill pid signal))
29
30 #!-sb-fluid (declaim (inline real-unix-killpg))
31 (sb!alien:define-alien-routine ("killpg" real-unix-killpg) sb!alien:int
32   (pgrp sb!alien:int)
33   (signal sb!alien:int))
34
35 ;;; Send the signal SIGNAL to the all the process in process group
36 ;;; PGRP. SIGNAL should be a valid signal number
37 (defun unix-killpg (pgrp signal)
38   (real-unix-killpg pgrp signal))
39
40 ;;; Set the current set of masked signals (those being blocked from
41 ;;; delivery).
42 ;;;
43 ;;; (Note: CMU CL had a SIGMASK operator to create masks, but since
44 ;;; SBCL only uses 0, we no longer support it. If you need it, you
45 ;;; can pull it out of the CMU CL sources, or the old SBCL sources;
46 ;;; but you might also consider doing things the SBCL way and moving
47 ;;; this kind of C-level work down to C wrapper functions.)
48 #!-sunos
49 (sb!alien:define-alien-routine ("sigsetmask" unix-sigsetmask)
50                                sb!alien:unsigned-long
51   (mask sb!alien:unsigned-long))
52 \f
53 ;;;; C routines that actually do all the work of establishing signal handlers
54 (sb!alien:define-alien-routine ("install_handler" install-handler)
55                                sb!alien:unsigned-long
56   (signal sb!alien:int)
57   (handler sb!alien:unsigned-long))
58 ;;; assert (though non-fatally) that there are no signals masked
59 (sb!alien:define-alien-routine "warn_when_signals_masked" sb!alien:void)
60
61 \f
62
63
64
65 ;;;; interface to enabling and disabling signal handlers
66
67 (defun enable-interrupt (signal handler)
68   (declare (type (or function fixnum (member :default :ignore)) handler))
69   (without-gcing
70    (let ((result (install-handler signal
71                                   (case handler
72                                     (:default sig_dfl)
73                                     (:ignore sig_ign)
74                                     (t
75                                      (sb!kernel:get-lisp-obj-address
76                                       handler))))))
77      (cond ((= result sig_dfl) :default)
78            ((= result sig_ign) :ignore)
79            (t (the (or function fixnum) (sb!kernel:make-lisp-obj result)))))))
80
81 (defun default-interrupt (signal)
82   (enable-interrupt signal :default))
83
84 (defun ignore-interrupt (signal)
85   (enable-interrupt signal :ignore))
86 \f
87 ;;;; default LISP signal handlers
88 ;;;;
89 ;;;; Most of these just call ERROR to report the presence of the signal.
90
91 ;;; SIGINT is handled like BREAK, except that ANSI BREAK ignores
92 ;;; *DEBUGGER-HOOK*, but we want SIGINT's BREAK to respect it, so that
93 ;;; SIGINT in --disable-debugger mode will cleanly terminate the system
94 ;;; (by respecting the *DEBUGGER-HOOK* established in that mode).
95 (defun sigint-%break (format-string &rest format-arguments)
96   (apply #'%break 'sigint format-string format-arguments))
97
98 (eval-when (:compile-toplevel :execute)
99   (sb!xc:defmacro define-signal-handler (name
100                                          what
101                                          &optional (function 'error))
102     `(defun ,name (signal info context)
103        (declare (ignore signal info))
104        (declare (type system-area-pointer context))
105        (/show "in Lisp-level signal handler" (sap-int context))
106        (,function ,(concatenate 'simple-string what " at #X~X")
107                   (with-alien ((context (* os-context-t) context))
108                     (sap-int (sb!vm:context-pc context)))))))
109
110 (define-signal-handler sigint-handler "interrupted" sigint-%break)
111 (define-signal-handler sigill-handler "illegal instruction")
112 (define-signal-handler sigtrap-handler "breakpoint/trap")
113 (define-signal-handler sigiot-handler "SIGIOT")
114 #!-linux
115 (define-signal-handler sigemt-handler "SIGEMT")
116 (define-signal-handler sigbus-handler "bus error")
117 (define-signal-handler sigsegv-handler "segmentation violation")
118 #!-linux
119 (define-signal-handler sigsys-handler "bad argument to a system call")
120 (define-signal-handler sigpipe-handler "SIGPIPE")
121
122 (defun sigalrm-handler (signal info context)
123   (declare (ignore signal info context))
124   (declare (type system-area-pointer context))
125   (cerror "Continue" 'sb!ext::timeout))
126
127 (defun sigquit-handler (signal code context)
128   (declare (ignore signal code context))
129   (throw 'sb!impl::toplevel-catcher nil))
130
131 (defun sb!kernel:signal-cold-init-or-reinit ()
132   #!+sb-doc
133   "Enable all the default signals that Lisp knows how to deal with."
134   (enable-interrupt sigint #'sigint-handler)
135   (enable-interrupt sigquit #'sigquit-handler)
136   (enable-interrupt sigill #'sigill-handler)
137   (enable-interrupt sigtrap #'sigtrap-handler)
138   (enable-interrupt sigiot #'sigiot-handler)
139   #!-linux
140   (enable-interrupt sigemt #'sigemt-handler)
141   (enable-interrupt sigfpe #'sb!vm:sigfpe-handler)
142   (enable-interrupt sigbus #'sigbus-handler)
143   (enable-interrupt sigsegv #'sigsegv-handler)
144   #!-linux
145   (enable-interrupt sigsys #'sigsys-handler)
146   (enable-interrupt sigpipe #'sigpipe-handler)
147   (enable-interrupt sigalrm #'sigalrm-handler)
148   (values))
149 \f
150 ;;;; etc.
151
152 ;;; CMU CL comment:
153 ;;;   Magically converted by the compiler into a break instruction.
154 (defun receive-pending-interrupt ()
155   (receive-pending-interrupt))
156 \f
157 ;;; stale code which I'm insufficiently motivated to test -- WHN 19990714
158 #|
159 ;;;; WITH-ENABLED-INTERRUPTS
160
161 (defmacro with-enabled-interrupts (interrupt-list &body body)
162   #!+sb-doc
163   "With-enabled-interrupts ({(interrupt function)}*) {form}*
164    Establish function as a handler for the Unix signal interrupt which
165    should be a number between 1 and 31 inclusive."
166   (let ((il (gensym))
167         (it (gensym)))
168     `(let ((,il NIL))
169        (unwind-protect
170            (progn
171              ,@(do* ((item interrupt-list (cdr item))
172                      (intr (caar item) (caar item))
173                      (ifcn (cadar item) (cadar item))
174                      (forms NIL))
175                     ((null item) (nreverse forms))
176                  (when (symbolp intr)
177                    (setq intr (symbol-value intr)))
178                  (push `(push `(,,intr ,(enable-interrupt ,intr ,ifcn)) ,il)
179                        forms))
180              ,@body)
181          (dolist (,it (nreverse ,il))
182            (enable-interrupt (car ,it) (cadr ,it)))))))
183 |#