ffi/unsafe/custodian: handle already-shutdown custodians
This commit is contained in:
parent
eb24c1e0b1
commit
63146e5451
|
@ -17,7 +17,9 @@ registering shutdown callbacks with custodians.}
|
||||||
|
|
||||||
Registers @racket[callback] to be applied (in atomic mode and an
|
Registers @racket[callback] to be applied (in atomic mode and an
|
||||||
unspecified Racket thread) to @racket[v] when @racket[custodian] is
|
unspecified Racket thread) to @racket[v] when @racket[custodian] is
|
||||||
shutdown. The result is a pointer that can be supplied to
|
shutdown. If @racket[custodian] is already shut down, the result is
|
||||||
|
@racket[#f] and @racket[v] is not registered. Otherwise, the result is
|
||||||
|
a pointer that can be supplied to
|
||||||
@racket[unregister-custodian-shutdown] to remove the registration.
|
@racket[unregister-custodian-shutdown] to remove the registration.
|
||||||
|
|
||||||
If @racket[at-exit?] is true, then @racket[callback] is applied when
|
If @racket[at-exit?] is true, then @racket[callback] is applied when
|
||||||
|
@ -43,26 +45,35 @@ be no longer registered to the custodian, while the finalizer for
|
||||||
|
|
||||||
|
|
||||||
@defproc[(unregister-custodian-shutdown [v any/c]
|
@defproc[(unregister-custodian-shutdown [v any/c]
|
||||||
[registration _cpointer])
|
[registration cpointer?])
|
||||||
void?]{
|
void?]{
|
||||||
|
|
||||||
Cancels a custodian-shutdown registration, where @racket[registration]
|
Cancels a custodian-shutdown registration, where @racket[registration]
|
||||||
is a previous result from @racket[register-custodian-shutdown] applied
|
is a previous result from @racket[register-custodian-shutdown] applied
|
||||||
to @racket[v].}
|
to @racket[v]. If @racket[registration] is @racket[#f], then no action
|
||||||
|
is taken.}
|
||||||
|
|
||||||
@defproc[(register-finalizer-and-custodian-shutdown
|
@defproc[(register-finalizer-and-custodian-shutdown
|
||||||
[v any/c]
|
[v any/c]
|
||||||
[callback (any/c . -> . any)]
|
[callback (any/c . -> . any)]
|
||||||
[custodian custodian? (current-custodian)]
|
[custodian custodian? (current-custodian)]
|
||||||
[#:at-exit? at-exit? any/c #f]
|
[#:at-exit? at-exit? any/c #f]
|
||||||
[#:weak? weak? any/c #f])
|
[#:weak? weak? any/c #f]
|
||||||
void?]{
|
[#:custodian-unavailable unavailable-callback ((-> void?) -> any) (lambda (reg-fnl) (reg-fnl))])
|
||||||
|
any]{
|
||||||
|
|
||||||
Registers @racket[callback] to be applied (in atomic mode) to
|
Registers @racket[callback] to be applied (in atomic mode) to
|
||||||
@racket[v] when @racket[custodian] is shutdown or when @racket[v] is
|
@racket[v] when @racket[custodian] is shutdown or when @racket[v] is
|
||||||
about to be collected by the garbage collector, whichever happens
|
about to be collected by the garbage collector, whichever happens
|
||||||
first. The @racket[callback] is only applied to @racket[v] once.
|
first. The @racket[callback] is only applied to @racket[v] once.
|
||||||
|
|
||||||
|
If @racket[custodian] is already shut down, then
|
||||||
|
@racket[unavailable-callback] is applied in tail position to a
|
||||||
|
function that registers a finalizer. By default, a finalizer is
|
||||||
|
registered anyway, but usually a better choice is to report an error.
|
||||||
|
If @racket[custodian] is not already shut down, then the result
|
||||||
|
from @racket[register-finalizer-and-custodian-shutdown] is @|void-const|.
|
||||||
|
|
||||||
@history[#:added "6.1.1.6"]}
|
@history[#:added "6.1.1.6"]}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -60,3 +60,20 @@
|
||||||
(for ([i 10])
|
(for ([i 10])
|
||||||
(unless (go)
|
(unless (go)
|
||||||
(error "shutdown failed")))
|
(error "shutdown failed")))
|
||||||
|
|
||||||
|
;; ----------------------------------------
|
||||||
|
;; Check that already-shutdown custodians are handled
|
||||||
|
|
||||||
|
(when (register-custodian-shutdown 88 void c)
|
||||||
|
(error "should have been #f due to shutdown"))
|
||||||
|
(unless (eq? 'cb
|
||||||
|
(register-finalizer-and-custodian-shutdown
|
||||||
|
88 void c
|
||||||
|
#:custodian-unavailable (lambda (proc)
|
||||||
|
(unless (and (procedure? proc)
|
||||||
|
(procedure-arity-includes? proc 0))
|
||||||
|
(error "should have received a thunk"))
|
||||||
|
'cb)))
|
||||||
|
(error "custodian-shutdown callback wasn't called"))
|
||||||
|
|
||||||
|
(unregister-custodian-shutdown 'anything #f)
|
||||||
|
|
|
@ -20,11 +20,13 @@
|
||||||
(unsafe-custodian-register custodian obj proc at-exit? weak?))
|
(unsafe-custodian-register custodian obj proc at-exit? weak?))
|
||||||
|
|
||||||
(define (unregister-custodian-shutdown obj mref)
|
(define (unregister-custodian-shutdown obj mref)
|
||||||
(unsafe-custodian-unregister obj mref))
|
(when mref
|
||||||
|
(unsafe-custodian-unregister obj mref)))
|
||||||
|
|
||||||
(define (register-finalizer-and-custodian-shutdown value callback
|
(define (register-finalizer-and-custodian-shutdown value callback
|
||||||
[custodian (current-custodian)]
|
[custodian (current-custodian)]
|
||||||
#:at-exit? [at-exit? #f])
|
#:at-exit? [at-exit? #f]
|
||||||
|
#:custodian-unavailable [custodian-unavailable (lambda (r) (r))])
|
||||||
(define done? #f)
|
(define done? #f)
|
||||||
(define (do-callback obj) ; called in atomic mode
|
(define (do-callback obj) ; called in atomic mode
|
||||||
(unless done?
|
(unless done?
|
||||||
|
@ -32,9 +34,14 @@
|
||||||
(callback obj)))
|
(callback obj)))
|
||||||
(define registration
|
(define registration
|
||||||
(register-custodian-shutdown value do-callback custodian #:at-exit? at-exit?))
|
(register-custodian-shutdown value do-callback custodian #:at-exit? at-exit?))
|
||||||
(register-finalizer value
|
(define (do-finalizer)
|
||||||
(lambda (obj)
|
(register-finalizer
|
||||||
(call-as-atomic
|
value
|
||||||
(lambda ()
|
(lambda (obj)
|
||||||
(unregister-custodian-shutdown obj registration)
|
(call-as-atomic
|
||||||
(do-callback obj))))))
|
(lambda ()
|
||||||
|
(unregister-custodian-shutdown obj registration)
|
||||||
|
(do-callback obj))))))
|
||||||
|
(if registration
|
||||||
|
(do-finalizer)
|
||||||
|
(custodian-unavailable do-finalizer)))
|
||||||
|
|
|
@ -1378,6 +1378,9 @@ static Scheme_Object *unsafe_custodian_register(int argc, Scheme_Object *argv[])
|
||||||
if (!SCHEME_PROCP(callback))
|
if (!SCHEME_PROCP(callback))
|
||||||
scheme_wrong_contract("unsafe-custodian-register", "procedure?", 2, argc, argv);
|
scheme_wrong_contract("unsafe-custodian-register", "procedure?", 2, argc, argv);
|
||||||
|
|
||||||
|
if (!scheme_custodian_is_available(custodian))
|
||||||
|
return scheme_false;
|
||||||
|
|
||||||
if (at_exit)
|
if (at_exit)
|
||||||
mr = scheme_add_managed_close_on_exit(custodian, v, call_registered_callback, callback);
|
mr = scheme_add_managed_close_on_exit(custodian, v, call_registered_callback, callback);
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in New Issue
Block a user