From 5ab2529768114220d55a644d93bc3f117de9f99e Mon Sep 17 00:00:00 2001 From: Vincent St-Amour Date: Fri, 3 May 2013 11:47:14 -0400 Subject: [PATCH] Fix race condition in `delay/thread'. 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 `#', which causes errors down the road. This was the cause of an intermittent failure in the TR test harness. (cherry picked from commit 0690ccd90fc75628946958b2b5e9c09b81a9fbb8) --- collects/racket/promise.rkt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/collects/racket/promise.rkt b/collects/racket/promise.rkt index 3015ff30f32..c052ae3bca3 100644 --- a/collects/racket/promise.rkt +++ b/collects/racket/promise.rkt @@ -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))))) @@ -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 + ;; `#', 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)))])