Skip to content

Commit

Permalink
Fix race condition in `delay/thread'.
Browse files Browse the repository at this point in the history
There's mutual dependence between promises and their threads. This may
cause a thread to start running before its promise is fully initialized,
in which case it will be `#<undefined>', which causes errors down the road.

This was the cause of an intermittent failure in the TR test harness.
(cherry picked from commit 0690ccd)
  • Loading branch information
stamourv authored and rmculpepper committed Jul 8, 2013
1 parent ac2c440 commit 5ab2529
Showing 1 changed file with 9 additions and 1 deletion.
10 changes: 9 additions & 1 deletion collects/racket/promise.rkt
Expand Up @@ -116,8 +116,9 @@
(unless (or (not group)
(thread-group? group))
(raise-argument-error 'delay/thread "(or/c thread-group? #f)" group))
(let ()
(let ([starter (make-semaphore)])
(define (run)
(semaphore-wait starter) ; wait until p is properly defined
(call-with-exception-handler
(lambda (e) (pset! p (make-reraise e)) (kill-thread (current-thread)))
(lambda () (pset! p (call-with-values thunk list)))))
Expand All @@ -128,6 +129,13 @@
(if group
(parameterize ([current-thread-group group]) (thread run))
(thread run)))))
;; The promise thread needs to wait until `p' is properly defined.
;; Otherwise, if the thread starts after `(thread run)' is evaluated, but
;; before `p' is defined, we end up doing `unsafe-struct-set!' on
;; `#<undefined>', which is bad.
;; This was the cause of an intermittent failure in the Typed Racket test
;; suite.
(semaphore-post starter)
p))
(define-syntax delay/thread*
(let ([kwds (list (cons '#:group #'(make-thread-group)))])
Expand Down

0 comments on commit 5ab2529

Please sign in to comment.