#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 |
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>
Attachments (1)
Change History (4)
Changed 6 years ago by
Attachment: | finalizer-fuzz.scm added |
---|
comment:1 Changed 6 years ago by
comment:3 Changed 5 years ago by
Milestone: | → 5.2 |
---|
Setting milestone so we can generate a list of fixed tickets in 5.2
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:
disable-interrupts
(gc #t)
call after a finalizer has been installed