~ chicken-core (chicken-5) 40160a8dce63228dfdeed8c1e9b742fae59d6c96
commit 40160a8dce63228dfdeed8c1e9b742fae59d6c96 Author: felix <felix@call-with-current-continuation.org> AuthorDate: Fri Dec 10 15:16:03 2010 +0100 Commit: felix <felix@call-with-current-continuation.org> CommitDate: Fri Dec 10 15:16:03 2010 +0100 finalizers are scanned first, then marked, or the first mark will not trigger a finalizer for the same object diff --git a/runtime.c b/runtime.c index 61efe5eb..ca3392b0 100644 --- a/runtime.c +++ b/runtime.c @@ -2809,12 +2809,16 @@ C_regparm void C_fcall C_reclaim(void *trampoline, void *proc) else { j = fcount = 0; + /* move into pending */ for(flist = finalizer_list; flist != NULL; flist = flist->next) { if(j < C_max_pending_finalizers) { if(!is_fptr(C_block_header(flist->item))) pending_finalizer_indices[ j++ ] = flist; } + } + /* mark */ + for(flist = finalizer_list; flist != NULL; flist = flist->next) { mark(&flist->item); mark(&flist->finalizer); } @@ -2829,7 +2833,7 @@ C_regparm void C_fcall C_reclaim(void *trampoline, void *proc) finalizers_checked = 1; if(pending_finalizer_count > 0 && gc_report_flag) - C_dbg(C_text("GC"), C_text("finalizers pending for rescan:\t %d (%d live)\n"), + C_dbg(C_text("GC"), C_text("%d finalizer(s) pending (%d live)\n"), pending_finalizer_count, live_finalizer_count); goto rescan; @@ -2839,7 +2843,7 @@ C_regparm void C_fcall C_reclaim(void *trampoline, void *proc) (and release finalizer node): */ if(pending_finalizer_count > 0) { if(gc_report_flag) - C_dbg(C_text("GC"), C_text("queueing %d finalizers\n"), pending_finalizer_count); + C_dbg(C_text("GC"), C_text("queueing %d finalizer(s)\n"), pending_finalizer_count); last = C_block_item(pending_finalizers_symbol, 0); assert(C_u_i_car(last) == C_fix(0)); diff --git a/tests/test-finalizers.scm b/tests/test-finalizers.scm index 512b0991..6ff33e1d 100644 --- a/tests/test-finalizers.scm +++ b/tests/test-finalizers.scm @@ -50,3 +50,16 @@ a fix that unfortunately disables finalizers in the interpreter (gc #t) (assert foo-f) + + +;; double finalizer + +(define n 0) +(define (bump . _) (set! n (add1 n))) +(define x (vector 1)) +(set-finalizer! x bump) +(set-finalizer! x bump) +(set! x #f) +(gc #t) +(print n) +(assert (= 2 n))Trap