﻿id	summary	reporter	owner	description	type	status	priority	milestone	component	version	resolution	keywords	cc	difficulty
1586	Context-switch from GC causes infinite GC loop	megane		"The following code causes the runtime to enter an infinite GC loop.

With help of Christian and Kon the cause was determined to be a
re-entry to the GC while GC'ing.

In the example below the thread running a finalizer runs out of its
quantum while running `spin` and does a context switch. The other
thread then starts a new GC which causes the issue.

Using `disable-interrupts` makes the issue go away. I haven't tested
if `disable-interrupts` is enough if the finalizer calls something
that was compiled without `disable-interrupts`.

I'll attach a fuzzer that can be used instead if the example doesn't
work.

{{{
;; (declare (disable-interrupts))
(cond-expand (chicken-5 (import (chicken base))
                        (import (chicken gc))
                        (import (srfi 18)))
             (else (use srfi-18)))

(define (spin count) (let lp2 ([i 0]) (when (< i count) (lp2 (add1 i)))))
(define (add-finalized) (set-finalizer! (list 'foo) (lambda (o) (spin 100))))

(let lp ([i 0])
  (while (< i 100)
    (print* i "" "")
    (let ([threads (list (make-thread
                          (lambda ()
                            (add-finalized) (add-finalized)
                            (gc #t)
                            (add-finalized) (add-finalized) (add-finalized))
                          ""thread-a"")
                         (make-thread (lambda () (gc #t) (add-finalized) (add-finalized))
                                      ""thread-b""))])
      (for-each thread-start! threads)
      (for-each thread-join! threads))
    (lp (add1 i))))

(print ""dones"")

;; Output:
;; $ csc gcloop2.scm && ./gcloop2
;; 0 1 2 3 4 5 6 7 8 9 10 11 12 <hangs here>
}}}
"	defect	closed	major	5.2	compiler	5.0.0	fixed	garbage collector context-switch threads scheduler		insane
