custom-hash: fix ephemeron race
The pattern (ephemeron-value (hash-ref! intern key (lambda () (make-ephemeron key (wrap key))))) is wrong, because a GC might happen between the time that the epehemeron is found in the table (or the time that the key was just added to the table) and the time that `ephemeron-value` is called to extract the value. If the key is not otherwise accessible, the value may no longer be in the ephemeron.
This commit is contained in:
parent
9772c05040
commit
d5aa191fb2
|
@ -168,10 +168,18 @@
|
|||
(define (wrap-key spec key)
|
||||
(define wrap (custom-spec-wrap spec))
|
||||
(define intern (custom-spec-intern spec))
|
||||
(ephemeron-value
|
||||
(hash-ref! intern key
|
||||
(lambda ()
|
||||
(make-ephemeron key (wrap key))))))
|
||||
;; Rely on the fact that a wrapped key is never represented as `#f`
|
||||
(define e (hash-ref intern key #f))
|
||||
(cond
|
||||
[(not e)
|
||||
(define wrapped-key (wrap key))
|
||||
(hash-set! intern key (make-ephemeron key wrapped-key))
|
||||
wrapped-key]
|
||||
[else
|
||||
(define wrapped-key (ephemeron-value e))
|
||||
(or wrapped-key
|
||||
;; Ephemeron was just cleared; try again
|
||||
(wrap-key spec key))]))
|
||||
|
||||
(define (hash-check-key who d key)
|
||||
(define spec (custom-hash-spec d))
|
||||
|
|
Loading…
Reference in New Issue
Block a user