~ 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