~ chicken-core (chicken-5) 63ebf0fa4b5b7644720c2d674366c72fb6b67659
commit 63ebf0fa4b5b7644720c2d674366c72fb6b67659 Author: megane <meganeka@gmail.com> AuthorDate: Fri Aug 9 13:39:36 2019 +0300 Commit: Peter Bex <peter@more-magic.net> CommitDate: Sat Sep 14 16:04:45 2019 +0200 Fix couple of hangs related to finalizers and (gc #t) Calling (gc #t) would get into an infinite no-progress loop in was being run in another thread. In that case the (##sys#run-pending-finalizers #f) call in is compiled with interrupts disabled the other thread never got to run again. * library.scm (##sys#run-pending-finalizers): Yield the current thread if pending finalizers are being run in another thread. Also signal an error if trying to re-enter without "state". This also would cause an infinite loop (when calling (gc #t) inside a finalizer). It would need special handling if re-entry is to be supported. Fixes #1586 Signed-off-by: Peter Bex <peter@more-magic.net> diff --git a/NEWS b/NEWS index 7d216375..c4ebe555 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,8 @@ (fixes #1627, thanks to John Cowan). - ##sys#check-exact and its C implementations C_i_check_exact and C_i_check_exact_2 have been deprecated (see also #1631). + - When garbage collector is manually invoked from a finalizer, raise + an error instead of hanging forever (fixes #1586). - Core libraries - There is now a srfi-88 module which contains just the three diff --git a/library.scm b/library.scm index bc0ef42c..2b5f4ef6 100644 --- a/library.scm +++ b/library.scm @@ -6072,10 +6072,11 @@ static C_word C_fcall C_setenv(C_word x, C_word y) { (define ##sys#run-pending-finalizers (let ((vector-fill! vector-fill!) (string-append string-append) - (working #f) ) + (working-thread #f) ) (lambda (state) - (unless working - (set! working #t) + (cond + ((not working-thread) + (set! working-thread ##sys#current-thread) (let* ((c (##sys#slot ##sys#pending-finalizers 0)) ) (when (##sys#debug-mode?) (##sys#print @@ -6097,7 +6098,15 @@ static C_word C_fcall C_setenv(C_word x, C_word y) { (##sys#slot ##sys#pending-finalizers i2)) ) )) (vector-fill! ##sys#pending-finalizers (##core#undefined)) (##sys#setislot ##sys#pending-finalizers 0 0) - (set! working #f) ) ) + (set! working-thread #f))) + (state) ; Got here due to interrupt; continue w/o error + ((eq? working-thread ##sys#current-thread) + (##sys#signal-hook + #:error '##sys#run-pending-finalizers + "re-entry from finalizer thread (maybe (gc #t) was called from a finalizer)")) + (else + ;; Give finalizer thread a change to run + (##sys#thread-yield!))) (cond ((not state)) ((procedure? state) (state)) (state (##sys#context-switch state) ) ) ) ))Trap