Opened 5 weeks ago

#1586 new defect

Context-switch from GC causes infinite GC loop

Reported by: megane Owned by:
Priority: major Milestone:
Component: compiler Version: 5.0.0
Keywords: garbage collector context-switch threads scheduler Cc:
Estimated difficulty: insane


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

;; (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))
                         (make-thread (lambda () (gc #t) (add-finalized) (add-finalized))
      (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>

Attachments (1)

finalizer-fuzz.scm (2.6 KB) - added by megane 5 weeks ago.

Download all attachments as: .zip

Change History (1)

Changed 5 weeks ago by megane

Note: See TracTickets for help on using tickets.