ffi/unsafe/custodian: fix weak-reference problem

Also fix a related problem in the `math' MPFR binding (which was
masked by the `ffi/unsafe/custodian' bug).
This commit is contained in:
Matthew Flatt 2012-12-11 09:30:15 -07:00
parent 764f6930ce
commit 5d57f6e497
3 changed files with 35 additions and 9 deletions

View File

@ -20,21 +20,23 @@
(get-ffi-obj 'scheme_remove_managed #f
(_fun _Scheme_Custodian_Reference-pointer _racket -> _void)))
(define (shutdown-callback impl proc+self)
((car proc+self) impl))
(define (shutdown-callback impl proc+box)
((car proc+box) impl))
(define shutdown-callback-box (box #f))
(define shutdown_callback
(cast shutdown-callback (_fun #:atomic? #t _racket _racket -> _void) _fpointer))
(cast shutdown-callback (_fun #:atomic? #t #:keep shutdown-callback-box
_racket _racket -> _void) _fpointer))
(define (register-custodian-shutdown obj proc [custodian (current-custodian)]
#:at-exit? [at-exit? #f]
#:weak? [weak? #f])
(define proc+self (cons proc
shutdown-callback)) ; proc as data -> ffi callback retained
(define proc+box (cons proc
shutdown-callback-box)) ; proc as data -> ffi callback retained
(if at-exit?
(scheme_add_managed_close_on_exit custodian
obj shutdown_callback proc+self)
obj shutdown_callback proc+box)
(scheme_add_managed custodian
obj shutdown_callback proc+self
obj shutdown_callback proc+box
(if weak? 0 1))))
(define (unregister-custodian-shutdown obj mref)

View File

@ -76,9 +76,14 @@
[(_ name type fail-thunk) (get-ffi-obj name mpfr-lib type fail-thunk)]))
(define mpfr-free-cache (get-mpfr-fun 'mpfr_free_cache (_fun -> _void)))
#;
(define mpfr-shutdown
(register-custodian-shutdown mpfr-free-cache (λ (free) (free))))
(register-custodian-shutdown
mpfr-free-cache ; acts as a "random" object for a shutdown handle
(λ (free)
;; The direct reference here is important, since custodian holds only
;; a weak reference to shutdown handle:
(mpfr-free-cache))))
;; ===================================================================================================
;; MPFR types

View File

@ -0,0 +1,19 @@
#lang racket/base
;; Not crashing means success for this stress test:
(let loop ([i 0] [l null])
(unless (= i 100)
(displayln "next")
(let ([l (if (zero? (random 5))
(begin
(printf "shutdown\n")
(for-each custodian-shutdown-all l)
null)
l)])
(let ([c (make-custodian)])
(parameterize ([current-custodian c])
(for ([i (random 10)]) (thread (lambda () (sleep 10))))
(parameterize ([current-namespace (make-base-namespace)])
(dynamic-require `math/bigfloat #f)))
(loop (add1 i) (cons c l))))))