From: gasbichl@informatik.uni-tuebingen.de (Martin Gasbichler)
Newsgroups: comp.lang.scheme.scsh
Subject: Re: alarm handler
Message-ID: <vyalmek9aq4.fsf@aubisque.informatik.uni-tuebingen.de>
Date: 26 Jan 2002 20:24:35 +0100
>>>>> "Ed" == Ed Kademan <kademan@phz.com> 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
this.
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?)
(begin
(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))))
--
Martin
Up |