summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Thompson <dthompson2@worcester.edu>2016-03-21 21:52:38 -0400
committerDavid Thompson <dthompson2@worcester.edu>2016-03-21 21:56:12 -0400
commit4410c8210392ba1f54d6670005cadb00ff189f04 (patch)
treec53ad4511b7db8d2bec5e61278fccc6b56bfcbb1
parentd0f26aea4f87391af77f5911c3e2ae19891287c8 (diff)
signal: Fix signal-sample.
signal-sample had a nasty nondeterministic bug where the newly created signal might actually be GC'd before it could be returned to the caller. This was able to happen because no reference to the signal was help between creating the signal and returning it. Reported-By: David Hashe <david.hashe@dhashe.com> * sly/signal.scm (signal-sample): Ensure that the garbage collector cannot reclaim the new signal before it is returned.
-rw-r--r--sly/signal.scm14
1 files changed, 9 insertions, 5 deletions
diff --git a/sly/signal.scm b/sly/signal.scm
index fc58b25..70c00ca 100644
--- a/sly/signal.scm
+++ b/sly/signal.scm
@@ -392,9 +392,9 @@ of SIGNAL was received."
"Create a new signal that takes on the value of SIGNAL every STEP
ticks."
;; To prevent memory leaks, the new signal is stored within a weak
- ;; value hash table and never bound to a variable within the main
- ;; body of the procedure. When this signal is GC'd, the sampling
- ;; will stop.
+ ;; value hash table and never bound to a variable within the
+ ;; coroutine. When this signal is GC'd, the coroutine will halt,
+ ;; and no more samples will be taken.
(let ((container (make-weak-value-hash-table 1)))
(define (get)
(hash-ref container 'signal))
@@ -405,13 +405,17 @@ ticks."
(signal-set! sampler (signal-ref signal))
#t)))
- (hash-set! container 'signal (make-signal (signal-ref signal)))
(coroutine
(let loop ()
(wait step)
(when (sample!)
(loop))))
- (get)))
+
+ ;; We maintain a reference to the new signal here so that the GC
+ ;; cannot collect it before it has been returned to the caller.
+ (let ((sampler (make-signal (signal-ref signal))))
+ (hash-set! container 'signal sampler)
+ sampler)))
(define (signal-every step)
"Create a new signal that emits STEP every STEP ticks."