Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#1586 closed defect (fixed)

Context-switch from GC causes infinite GC loop

Reported by: megane Owned by:
Priority: major Milestone: 5.2
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 years ago.

Download all attachments as: .zip

Change History (4)

Changed 5 years ago by megane

Attachment: finalizer-fuzz.scm added

comment:1 Changed 5 years ago by megane

The implication of this is that a program will have a greater than zero change of hanging with the gc-loop if these conditions are met:

  • The program uses threads
  • The program has a finalizer that has been compiled without disable-interrupts
  • There is a (gc #t) call after a finalizer has been installed

comment:2 Changed 5 years ago by sjamaan

Resolution: fixed
Status: newclosed

Fixed with 63ebf0fa

comment:3 Changed 5 years ago by sjamaan

Milestone: 5.2

Setting milestone so we can generate a list of fixed tickets in 5.2

Note: See TracTickets for help on using tickets.