diff options
author | David Thompson <dthompson2@worcester.edu> | 2016-03-21 21:52:38 -0400 |
---|---|---|
committer | David Thompson <dthompson2@worcester.edu> | 2016-03-21 21:56:12 -0400 |
commit | 4410c8210392ba1f54d6670005cadb00ff189f04 (patch) | |
tree | c53ad4511b7db8d2bec5e61278fccc6b56bfcbb1 | |
parent | d0f26aea4f87391af77f5911c3e2ae19891287c8 (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.scm | 14 |
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." |