[gambit-list] Interrupted in wait-for-io
Christian
christian at pflanze.mine.nu
Wed Jan 4 15:30:09 EST 2006
At 10:28 Uhr -0500 04.01.2006, Marc Feeley wrote:
>It is possible using undocumented procedures. Here's what you want:
Thank you.
>I'm planning to change this so that the default user-interrupt-
>handler behaves like exceptions, i.e. the default will be to
>terminate the program after displaying "*** INTERRUPTED IN ...".
The default for unix programs is that SIGINT makes them terminate
*and deliver that fact to the parent* (through wait(2) the parent can
know if the child terminated because of a signal and which one it
was). If you trap SIGINT, then afaik the only way to make the parent
know we are terminating because of a signal is to remove our signal
handler and then killing ourselves again. This poses the question as
to why a signal handler has been installed in the first place.
I think that printing a message and exiting with an error code is a
nonstandard and thus suboptimal solution, and that not installing
signal handlers at all unless really necessary would be, in
principle, a better solution. (I'm mainly coming from perl, which
works that way.) I don't want to suggest to give this a high priority
though and also have never really programmed on non-unix systems.
>With the runtime option "-:d" the system will instead start a REPL.
>With the runtime option "-:d0" the program will terminate silently.
>However, when inside a REPL (such as the one normally started in
>interactive mode), a SIGINT will start a nested REPL.
That makes sense to me.
>>(*) that leads to another question I've been wondering about:
>>parameterize doesn't accept procedures which aren't parameters (it
>>checks their type). This makes the above suggestion impossible to
>>be implement transparently of course, since it would require
>>running code other than just for setting the dynamic value (**).
>
>I don't understand what you mean.
Here's a normal parameter p1, and a self-written parameter like
function p2 which has the side effect of something like initializing
signal setup if not done already:
(define p1 (make-parameter #f))
(define pseudo-signal-handler-hook #f)
(define p2
(let ((absent (gensym))
(value #f))
(lambda (#!optional (newvalue absent))
(if (eq? newvalue absent)
value
(begin
(if (not pseudo-signal-handler-hook)
(set! pseudo-signal-handler-hook
(lambda ()
(display "hello world\n"))))
(set! value newvalue))))))
; > (p1)
; #f
; > (p1 "hello")
; > (p1)
; "hello"
; > (p2)
; #f
; > pseudo-signal-handler-hook
; #f
; > (p2 "world")
; > (p2)
; "world"
; > pseudo-signal-handler-hook
; #<procedure #2 pseudo-signal-handler-hook>
; > (#2)
; hello world
; > (begin (parameterize ((p1 "a")) (display (p1))(newline)) (display
(p1))(newline))
; a
; #f
; > (begin (parameterize ((p2 "a")) (display (p2))(newline)) (display
(p2))(newline))
; *** ERROR IN (console)@3.8 -- PARAMETER expected
; 1>
The problem is that my side-effecting pseudo parameter cannot be
transparently used with parameterize. It occured to me as an
unnecessary drawback when I first realized that parameters were
procedures but procedures can't be parameters. I did assume
parameterize were implemented about like this (e.g. querying the old
value, storing in lexical context, setting new value with
dynamic-wind):
; (let ((#:g10 (p2)))
; (dynamic-wind
; (lambda () (p2 "a"))
; (lambda () (display (p2)) (newline))
; (lambda () (p2 #:g10))))
(let ((#:var2 "a"))
(let ((#:swap4 (lambda ()
(let ((#:tmp3 (p2)))
(p2 #:var2) (set! #:var2 #:tmp3)))))
(dynamic-wind #:swap4
(lambda () (display (p2)) (newline))
#:swap4)))
; as generated by this macro:
(define-macro (my-parameterize bindings . body)
(let* ((b-alist (map (lambda (l)
(cons l
(gensym 'var)))
bindings))
(b->var (lambda (l)
(cdr (assoc l b-alist))))
(b->name car)
(b->init cadr)
(tmp (gensym 'tmp))
(swap (gensym 'swap)))
`(let ,(map (lambda (l)
(list (b->var l)
(b->init l)))
bindings)
(let ((,swap
(lambda ()
,@ (map (lambda (l)
`(let ((,tmp (,(b->name l))))
(,(b->name l) ,(b->var l))
(set! ,(b->var l) ,tmp)))
bindings))))
(dynamic-wind
,swap
(lambda ()
,@ body)
,swap)))))
I know this implementation of parameterize has a problem though:
dynamic-wind is not safe when using exceptions. Why? I find this
especially strange considering that I thought with-exception-catcher
was implemented using continuations.
Which other reasons are there for implementing parameters
differently? Performance or semantics? I guess the above
implementation would be rather slow. I've taken a cursory look at the
srfi-39 document and discussion archive, but most of it is over my
head right now, I'll reread later.
So, it seems that the "most natural way" of how parameterize would be
implemented is not the best and thus I shouldn't expect to be able to
put callbacks into a supposedly lowlevel dynamic bindings mechanism.
>>What's the reason for this restriction?
>>
>
>Parameters are special procedures that contain a key. This key is
>used to lookup the binding of the parameter. The machinery is quite
>complex (see _thread.scm).
I'll reread it later.
>>((**) without this, the user would have to run some
>>(user-interrupt- initialize!) hook first -- at least, that might be
>>better for thread safety?)
Thanks,
Christian.
More information about the Gambit-list
mailing list