scheme shell

From: (Martin Gasbichler)
Newsgroups: comp.lang.scheme.scsh
Subject: Re: alarm handler
Message-ID: <>
Date: 26 Jan 2002 20:24:35 +0100

>>>>> "Ed" == Ed Kademan <> writes:

Ed> I am trying to write a scsh program that executes a process in such a
Ed> way that if it doesn't complete in a certain time period the program
Ed> gives up on it.  I've never been entirely successful in getting this
Ed> to work and things seem to have gotten worse in scsh-0.6.0.

Ed> I have a procedure called `execute/timeout' that takes two
Ed> arguments---a subprocedure and a number of seconds---and attempts to
Ed> execute the subprocedure.  The intended behavior is that if the
Ed> subprocedure finishes in the alloted number of seconds then
Ed> execute/timeout returns its value.  If it doesn't finish the return
Ed> value is 'timeout.  The actual behavior is something else.  (I have
Ed> appended the definition of execute/timeout and a transcript of a
Ed> sample run below.)

Ed> I would not be happy with the function even if it somehow worked.  It
Ed> seems to me that the alarm interrupt handler should clean up after the
Ed> incomplete subprocedure, but I don't see how to do that.  I am
Ed> prepared to believe that there is an entirely better way of writing
Ed> the function using threads but I don't see how to do that either.

Ed> My purpose in sending this message is to ask if anyone has already
Ed> written a procedure that does what I am describing, or to ask if they
Ed> have pointers on how to do so.  Also, I want to describe how my
Ed> procedure behaves in case it demonstrates a bug in scsh---but the more
Ed> I think about it the more I believe this is my fault.

Ed> Thanks for reading this.
Ed> -----------------------------------------------------------------
Ed> ;;; This is scsh-0.6.0 on Solaris2.6.

Ed>   (define (execute/timeout proc sec)
>> (let ((alrm-handler (interrupt-handler interrupt/alrm))
>> (result 
>> (call-with-current-continuation
>> (lambda (break)
>> (set-interrupt-handler interrupt/alrm
>> (lambda (i) (break 'timeout)))
>> (itimer sec)
>> (with-enabled-interrupts (interrupt-set interrupt/alrm)
>> (proc))))))
>> (set-interrupt-handler interrupt/alrm alrm-handler)
>> (itimer 0)
>> result))

I've now realized what you are trying to do and I withdraw my
statement from yesterday: this is not a bug in scsh ;-)

You are calling a continuation within a signal handler. This will not
work for various reasons, one of them is that the handler is running
in a different thread. Maybe I should put a note in the manual about

Using threads however, your problem is quite easy to resolve:

,open locks placeholders threads

(define (execute/timeout proc sec)
  (let ((lock (make-lock))
        (done? #f)
        (result (make-placeholder)))
    (let ((maybe-set-result! 
	   (lambda (val)
	     (obtain-lock lock)
	     (if (not done?)
		   (set! done? #t)
		   (placeholder-set! result val)))
	     (release-lock lock))))
    (spawn (lambda ()
             (sleep (* sec 1000))
	     (maybe-set-result! 'timeout)))
    (spawn (lambda ()
	     (maybe-set-result! (proc))))
    (placeholder-value result))))