nested guard causes infinte loop

Issue #189 resolved
Takashi Kato repo owner created an issue

Found in https://github.com/cisco/ChezScheme/issues/87

(define (raise-proc1)
  (raise-continuable 'test)
  (display "Returning from raise-proc1\n"))

(define (raise-proc2)
  (raise 'test)
  ;; we will never reach here
  (display "Returning from raise-proc2\n"))

(define (guard-proc-inner f)
  (guard (c
      (#f #f))
     (f))
  (display "Returning from inner re-raised continuable exception\n"))

(define (guard-proc-outer f)
  (guard (c
      (#f #f))
     (guard-proc-inner f))
  (display "Returning from outer re-raised continuable exception\n"))

(with-exception-handler
 (lambda (k)
   #f)
 (lambda ()
   (guard-proc-outer raise-proc1)))

(display "Normal exit\n\n")

(with-exception-handler
 (lambda (k)
   #f)
 (lambda ()
   (guard-proc-outer raise-proc2)))

;; never executed
(display "Normal exit\n\n")

Above goes into infinite loop with the condition of

#<condition
 #<&error>
 #<&message attempt to return from C continuation boundary.>
 #<stack-trace cause=#f>
>

Comments (4)

  1. Takashi Kato reporter

    A smaller reproducible code is here:

    (with-exception-handler
     (lambda (k)  #t)
     (lambda ()
       (guard (e (#f #f))
         (error 'test "msg"))))
    

    This is continuation boundary problem. Since our raise and raise-continuable are implemented in C world, then we need to put a boundary when handlers are invoked.

  2. Takashi Kato reporter

    The change causes other issue. This would consume all stack:

    (import (rnrs) (sagittarius threads))
    
    (define (raise-and-guard)
      (guard (e (else (print e) #t)) (error 'who "msg")))
    
    (thread-join! (thread-start! (make-thread raise-and-guard)))
    
  3. Log in to comment