Summary

Context-switch from GC causes infinite GC loop

Metadata

Attachments

Description

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>

Changes and comments

[2019-02-16 13:49:23 UTC] megane attached finalizer-fuzz.scm (description=#f)

[2019-04-20 17:34:37 UTC] megane wrote:

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

[2019-09-14 16:10:04 UTC] sjamaan changed status from new to closed

[2019-09-14 16:10:04 UTC] sjamaan set resolution to fixed

[2019-09-14 16:10:04 UTC] sjamaan wrote:

Fixed with 63ebf0fa

[2019-09-14 16:10:40 UTC] sjamaan set milestone to 5.2

[2019-09-14 16:10:40 UTC] sjamaan wrote:

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