bug-guile
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: signal handling different in 1.8.3 than 1.8.1?


From: Gregory Marton
Subject: Re: signal handling different in 1.8.3 than 1.8.1?
Date: Fri, 6 Jun 2008 15:56:49 -0400 (EDT)

Higher-level question:

As these are asynchronous, (alarm 10) could actually set off the alarm at any time after ten seconds. Is it still possible to write with-timeout?

(define (with-timeout t thunk . handler)
     (let ((time-left (alarm 0))        ;;time left on an outer alarm
          (start-time (current-time)))
       (alarm time-left)        ;;continue the outer countdown
       (catch 'parent-timeout-error
        (lambda ()
          (catch 'timeout-error
            (lambda ()
              (with-sigaction SIGALRM
                (lambda (sig)
                  (if (and (< time-left t) (not (equal? time-left 0)))
                      (throw 'parent-timeout-error)
                      (throw 'timeout-error)))
                #f
                (lambda ()
                  (ensure
                   (lambda ()
                     (begin
                      (if (or (< t time-left) (equal? time-left 0))
                          (alarm t)) ;;time out in the shorter time, not the 
most recently set time
                      (thunk)))
                   (lambda ()
                     (if (equal? time-left 0)
                         (alarm 0)
                         ;;reset the outer alarm if there was one, subtracting 
time taken by the thunk
                         (let* ((time-taken (- (current-time) start-time))
                                (time-remaining (- time-left time-taken)))
                           (alarm 0)
                           (if (<= 0 time-remaining) ; guile 1.3 is broken and
                               (alarm time-remaining) ; this can happen.
                               (begin
                                 (raise SIGALRM)      ;better late than never?
                                 (sleep 1))))))))))
            (lambda (k . v)
              (if (null? handler)
                  (throw k)
                  ((car handler))))))
        (lambda (k . v)
          (raise SIGALRM) (sleep 1)))))

To put it another way, I sure would like to have some guarantees about when some asynchronous things will happen. Even with the (sleep 1)s, my with-timeout test cases fail.

Thanks,
Grem


Aha! So (sleep 0) did nothing, but interestingly (sleep 1) did -- but it didn't sleep 1!

So if I write this as
     (let ((sigcalled #f))
       (with-sigaction
        SIGALRM (lambda (sig) (set! sigcalled #t)) #f
        (lambda () (raise SIGALRM) (sleep 1)))
       (assert sigcalled "we set and handled an alarm"))
(assert-equal orig (sigaction SIGALRM) "returned to the original state")
     (let ((outer "nop")
           (inner "nop"))
       (with-sigaction
           SIGALRM (lambda (sig) (set! outer "outer")) #f
           (lambda ()
             (with-sigaction
                 SIGALRM (lambda (sig) (set! inner "inner")) #f
                 (lambda ()
                   (raise SIGALRM) (sleep 1)))
             (raise SIGALRM) (sleep 1)))
       (and (assert-equal "inner" inner "inner sig got handled")
            (assert-equal "outer" outer "outer sig got handled")))
(assert-equal orig (sigaction SIGALRM) "returned to the original state")

then it passes. I thought it should never reach those sleeps -- what's going on? Also, it effectively doesn't reach the sleeps: the program passes the tests very quickly.

Grem

On Tue, 3 Jun 2008, Ludovic Courtès wrote:

The following message is a courtesy copy of an article
that has been posted to gmane.lisp.guile.bugs as well.

Hello,

Gregory Marton <address@hidden> writes:

The following message is a courtesy copy of an article
that has been posted to gmane.lisp.guile.bugs as well.

Is address@hidden now out of date?   I may have to get a
newsreader. Are they mirrored?

No, address@hidden' is not outdated: it's just that I'm posting
through Gmane (http://gmane.org/), which is a mail/news bi-directional
gateway.  The above notice is issued (I think) by Gmane someone is
explicitly Cc'd to a newsgroup post.

Nevertheless, it has consistently passed in 1.8.1 and consistently
fails in 1.8.3 with no other changes.

Sure, but a quick glance at `NEWS' didn't reveal anything obviously
related to the problem at hand.

BTW, you might want to even switch to 1.8.5 while you're at it.

call-with-unblocked-asyncs complains:
    misc-error: asyncs already unblocked

OK, so it's not needed.

With (sleep 0) is no different than without.

I just tried and it depends on where you place it.  For instance, a
`format' call (which also does `SCM_TICK' as a side effect) within the
second lambda passed to `ensure' in `with-sigaction' does the trick.

The key insight here is that signal delivery in Guile is asynchronous,
so you can't know for sure when it will happen.  It'd be nice to be able
to force system asyncs to run, though.

As to why there's such a reproducible difference between 1.8.1 and
1.8.3, maybe you could try using `git-bisect' to find out which change
set between tags `release_1-8-1' and `release_1-8-3' introduced the
change in behavior.  I think it's probably a side-effect of some
unrelated change but again, a valid side-effect.

Hope this helps,
Ludovic.




--
------ __@   Gregory A. Marton                http://csail.mit.edu/~gremio/
--- _`\<,_                                                                .
-- (*)/ (*)       Am I sure?  Sure is just what I'm not anything but!
~~~~~~~~~~~~~~~~-~~~~~~~~_~~~_~~~~~v~~~~^^^^~~~~~--~~~~~~~~~~~~~~~++~~~~~~~

reply via email to

[Prev in Thread] Current Thread [Next in Thread]