/usr/share/scsh-0.6/scsh/sighandlers.scm is in scsh-common-0.6 0.6.7-8.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | ;;; Copyright (c) 1993 by Olin Shivers.
;;; Signal handler system
;;; The principal trickiness here is that we have to interface to Unix signals
;;; *through* an intermediate interface, the S48 vm's idea of interrupts.
;;; So there is a difference between delivering a signal to the underlying
;;; Unix process and delivering it to the program that runs on the VM.
;;;
;;; One effect is that we have two separate codes for the same thing -- the
;;; Unix signal code, and the S48 interrupt value. E.g., SIGNAL/TSTP and
;;; INTERRUPT/TSTP.
;;; These system calls can return EINTR or restart. In order for the S48 vm's
;;; interrupt system to detect a signal and invoke the handler, they *must*
;;; return EINTR, and this must cause a return from C to Scheme.
;;;
;;; open close dup2 accept connect
;;; read recv recvfrom recvmsg
;;; write send sendto sendmsg
;;; select
;;; wait
;;; fcntl* ioctl
;;; sigsuspend
;;; HP-UX, but I don't use: poll lockf msem_lock msgsnd msgrcv semop
;;;
;;; * Only during a F_SETLKW
;;;
;;; From rts/interrupt.scm (package interrupts, interface interrupts-interface)
;;; WITH-INTERRUPTS INTERRUPT-HANDLERS SET-ENABLED-INTERRUPTS !
;;; ENABLED-INTERRUPTS
;;; Must define WITH-INTERRUPTS* and WITH-INTERRUPTS.
;;; Map a Unix async signal to its S48 interrupt value.
;;; -1 => Not defined.
(import-lambda-definition %signal->interrupt (sig) "sig2interrupt")
(define (signal->interrupt sig)
(let ((int (%signal->interrupt sig)))
(if (>= int 0) int
(error "Unix signal has no Scheme 48 interrupt." sig))))
(define (interrupt-enabled? int mask)
(interrupt-in-set? int mask))
(define (interrupt-enable int mask)
(insert-interrupt int mask))
(define *enabled-interrupts*
(let lp ((i 0) (mask 0))
(if (= i number-of-interrupts)
mask
(lp (+ i 1) (interrupt-enable i mask)))))
(define (enabled-interrupts) *enabled-interrupts*)
(define *pending-interrupts* 0)
(define (interrupt-pending? int)
(interrupt-in-set? int *pending-interrupts*))
(define (make-interrupt-pending int)
(set! *pending-interrupts* (insert-interrupt int *pending-interrupts*)))
(define (remove-pending-interrupt int)
(set! *pending-interrupts* (remove-interrupt int *pending-interrupts*)))
;;; I'm trying to be consistent about the ! suffix -- I don't use it
;;; when frobbing process state. This is not a great rule; perhaps I
;;; should change it.
;;;
;;; I think you should...
(define (set-enabled-interrupts new-enabled-interrupts)
(let ((old-enabled-interrupts *enabled-interrupts*))
;;; set it here so the handlers see the correct value
(set! *enabled-interrupts* new-enabled-interrupts)
(do ((int 0 (+ int 1)))
((= int number-of-interrupts) new-enabled-interrupts)
(let ((old-state (interrupt-enabled? int old-enabled-interrupts))
(new-state (interrupt-enabled? int new-enabled-interrupts)))
(if (and (not old-state) new-state (interrupt-pending? int))
(begin
(remove-pending-interrupt int)
(call-interrupt-handler int)))))))
(define-simple-syntax (with-enabled-interrupts interrupt-set body ...)
(begin
(with-enabled-interrupts* interrupt-set (lambda () body ...))))
(define (with-enabled-interrupts* interrupt-set thunk)
(let ((before *enabled-interrupts*))
(set-enabled-interrupts interrupt-set)
(let ((return (thunk)))
(set-enabled-interrupts before)
return)))
(define *interrupt-handlers-vector*)
(define (install-fresh-interrupt-handlers-vector!)
(set! *interrupt-handlers-vector* (make-vector number-of-interrupts #t)))
(define (interrupt-handlers-vector)
*interrupt-handlers-vector*)
(define (interrupt-handler-ref int)
(if (or (< int 0) (>= int number-of-interrupts))
(error "ill signum in interrupt-handler-ref" int)
(vector-ref *interrupt-handlers-vector* int)))
(define (call-interrupt-handler int)
(let ((handler (interrupt-handler-ref int)))
(case handler
((#t) ((vector-ref default-int-handler-vec int) (enabled-interrupts)))
((#f) (if #f #f))
(else (handler (enabled-interrupts))))))
;;; Get/Set signal handlers
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; When you set a signal's handler to "default," if the default for that
;;; signal is something other than "ignore," we actually install this guy.
;;; When he is called by the S48 interrupt system, he'll magically make
;;; the default action happen (by calling C code that *really* sets the
;;; handler to SIGDFL, and then re-sending the signal). This basically
;;; terminates the process, since if the default isn't "ignore," it's always
;;; "terminate" of some kind. Doing it this way means the exit code given
;;; to our waiting parent proc correctly reflects how we died, and also
;;; makes the core dump happen if it should. Details, details.
(import-lambda-definition %do-default-sigaction (signal) "do_default_sigaction")
(define default-int-handler-vec
;; Non-Unix-signal interrupts just get their default values from
;; the current value of I-H.
(let ((v (make-vector 32)))
(do ((sig 31 (- sig 1))) ; For each Unix signal
((< sig 0)) ; make & install a default
(let ((i (%signal->interrupt sig))) ; signal handler.
(if (>= i 0) ; Don't mess with non-signal interrupts.
(vector-set! v i (if (memv sig signals-ignored-by-default)
(lambda (enabled-interrupts) #f)
(lambda (enabled-interrupts)
(%do-default-sigaction sig)))))))
v))
;;; HANDLER is #f (ignore), #t (default), or a procedure taking an integer
;;; argument. The interrupt is delivered to a procedure by (1) setting the
;;; ENABLED-INTERRUPTS register to 0 (i.e., blocking all interrupts), and (2)
;;; applying the procedure to the previous value of the ENABLED-INTERRUPTS
;;; register. If the procedure returns normally, the ENABLED-INTERRUPTS
;;; register will be restored to its previous value.
(define (set-interrupt-handler int handler)
(if (or (< int 0) (>= int number-of-interrupts))
(error "ill signum in set-interrupt-handler!" int)
(let ((old-handler (vector-ref *interrupt-handlers-vector* int)))
(vector-set! *interrupt-handlers-vector* int handler)
old-handler)))
(define (interrupt-handler int)
(interrupt-handler-ref int))
(define (with-scsh-sighandlers interactive? thunk)
(install-fresh-interrupt-handlers-vector!)
(do ((sig 32 (- sig 1)))
((< sig 0))
(let ((i (%signal->interrupt sig)))
(if (not (or (= i -1)
(= sig signal/alrm))) ; Leave alarm handler alone.
(set-interrupt-handler
i
#t))))
(let ((scsh-initial-thread ((structure-ref threads-internal current-thread))))
(if (not (eq? (thread-name scsh-initial-thread)
'scsh-initial-thread))
(error "sighandler did not find scsh-initial-thread, but"
scsh-initial-thread))
;; Note: this will prevent any other system to work, since it pushes
;; a new command level !
(if interactive?
(set-interrupt-handler interrupt/keyboard
(lambda stuff
((structure-ref threads-internal schedule-event)
scsh-initial-thread
(enum
(structure-ref threads-internal event-type)
interrupt)
(enum interrupt keyboard))))))
(run-as-long-as
deliver-interrupts
thunk
(structure-ref threads-internal spawn-on-root)
'deliver-interrupts))
(define (deliver-interrupts)
(let lp ((last ((structure-ref sigevents most-recent-sigevent))))
(let* ((event ((structure-ref sigevents next-sigevent-set)
last full-interrupt-set))
(interrupt ((structure-ref sigevents sigevent-type) event)))
(if (interrupt-enabled? interrupt (enabled-interrupts))
(call-interrupt-handler interrupt)
(make-interrupt-pending interrupt))
(lp event))))
;;; Dealing with synchronous signals
(import-lambda-definition ignore-signal (sig) "ignore_signal")
(import-lambda-definition handle-signal-default (sig) "handle_signal_default")
;;; I am ashamed to say the 33 below is completely bogus.
;;; What we want is a value that is 1 + max interrupt value.
(define int->sig-vec
(let ((v (make-vector 33 #f)))
(do ((sig 32 (- sig 1)))
((< sig 0))
(let ((i (%signal->interrupt sig)))
(if (not (= i -1)) (vector-set! v i sig))))
v))
(define (int->signal i) (and (<= 0 i 32) (vector-ref int->sig-vec i)))
|