add custodian-based unloading of foreign libraries
Specificially, add a `#:custodian` argument to `ffi-lib`.
This commit is contained in:
parent
276a102d6a
commit
3024b77ba5
|
@ -18,7 +18,8 @@ Returns @racket[#t] if @racket[v] is a @deftech{foreign-library value},
|
||||||
[version (or/c string? (listof (or/c string? #f)) #f) #f]
|
[version (or/c string? (listof (or/c string? #f)) #f) #f]
|
||||||
[#:get-lib-dirs get-lib-dirs (-> (listof path?)) get-lib-search-dirs]
|
[#:get-lib-dirs get-lib-dirs (-> (listof path?)) get-lib-search-dirs]
|
||||||
[#:fail fail (or/c #f (-> any)) #f]
|
[#:fail fail (or/c #f (-> any)) #f]
|
||||||
[#:global? global? any/c (eq? 'global (system-type 'so-mode))])
|
[#:global? global? any/c (eq? 'global (system-type 'so-mode))]
|
||||||
|
[#:custodian custodian (or/c 'place custodian? #f) #f])
|
||||||
any]{
|
any]{
|
||||||
|
|
||||||
Returns a @tech{foreign-library value} or the result of @racket[fail].
|
Returns a @tech{foreign-library value} or the result of @racket[fail].
|
||||||
|
@ -115,23 +116,43 @@ library's symbols are not made available for future resolution. This
|
||||||
local-versus-global choice does not affect whether the library's
|
local-versus-global choice does not affect whether the library's
|
||||||
symbols are available via @racket[(ffi-lib #f)].
|
symbols are available via @racket[(ffi-lib #f)].
|
||||||
|
|
||||||
|
If @racket[custodian] is @racket['place] or a custodian, the
|
||||||
|
library is unloaded when a custodian is shut down---either the given
|
||||||
|
custodian or the place's main custodian if @racket[custodian] is
|
||||||
|
@racket['place]. When a library is unloaded, all references to the
|
||||||
|
library become invalid. Supplying @racket['place] for
|
||||||
|
@racket[custodian] is consistent with finalization via
|
||||||
|
@racketmodname[ffi/unsafe/alloc] but will not, for example, unload the
|
||||||
|
library when hitting in the @onscreen{Run} button in DrRacket.
|
||||||
|
Supplying @racket[(current-custodian)] for @racket[custodian] tends to
|
||||||
|
unload the library for eagerly, but requires even more care to ensure
|
||||||
|
that library references are not accessed after the library is
|
||||||
|
unloaded.
|
||||||
|
|
||||||
|
If @racket[custodian] is @racket[#f], the loaded library is associated
|
||||||
|
with Racket (or DrRacket) for the duration of the process. Loading
|
||||||
|
again with @racket[ffi-lib], will not force a re-load of the
|
||||||
|
corresponding library.
|
||||||
|
|
||||||
|
When @racket[ffi-lib] returns a reference to a library that was
|
||||||
|
previously loaded within the current place, it increments a
|
||||||
|
reference count on the loaded library rather than loading the library
|
||||||
|
fresh. Unloading a library reference decrements the reference count
|
||||||
|
and requests unloading at the operating-system level only if the
|
||||||
|
reference count goes to zero.
|
||||||
|
|
||||||
The @racket[ffi-lib] procedure logs (see @secref["logging" #:doc '(lib
|
The @racket[ffi-lib] procedure logs (see @secref["logging" #:doc '(lib
|
||||||
"scribblings/reference/reference.scrbl")]) on the topic
|
"scribblings/reference/reference.scrbl")]) on the topic
|
||||||
@racket['ffi-lib]. In particular, on failure it logs the paths
|
@racket['ffi-lib]. In particular, on failure it logs the paths
|
||||||
attempted according to the rules above, but it cannot report the
|
attempted according to the rules above, but it cannot report the
|
||||||
paths tried due to the operating system's library search path.
|
paths tried due to the operating system's library search path.
|
||||||
|
|
||||||
Due to the way the operating system performs dynamic binding, loaded
|
|
||||||
libraries are associated with Racket (or DrRacket) for the duration of
|
|
||||||
the process. Re-evaluating @racket[ffi-lib] (or hitting the
|
|
||||||
@onscreen{Run} button in DrRacket) will not force a re-load of the
|
|
||||||
corresponding library.
|
|
||||||
|
|
||||||
@history[#:changed "6.1.0.5" @elem{Changed the way a version number is
|
@history[#:changed "6.1.0.5" @elem{Changed the way a version number is
|
||||||
added with a @filepath{.dll} suffix
|
added with a @filepath{.dll} suffix
|
||||||
to place it before the suffix,
|
to place it before the suffix,
|
||||||
instead of after.}
|
instead of after.}
|
||||||
#:changed "7.3.0.3" @elem{Added logging.}]}
|
#:changed "7.3.0.3" @elem{Added logging.}
|
||||||
|
#:changed "7.4.0.7" @elem{Added the @racket[#:custodian] argument.}]}
|
||||||
|
|
||||||
@defproc[(get-ffi-obj [objname (or/c string? bytes? symbol?)]
|
@defproc[(get-ffi-obj [objname (or/c string? bytes? symbol?)]
|
||||||
[lib (or/c ffi-lib? path-string? #f)]
|
[lib (or/c ffi-lib? path-string? #f)]
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
(require '#%foreign setup/dirs racket/unsafe/ops racket/private/for
|
(require '#%foreign setup/dirs racket/unsafe/ops racket/private/for
|
||||||
(only-in '#%unsafe
|
(only-in '#%unsafe
|
||||||
unsafe-thread-at-root
|
unsafe-thread-at-root
|
||||||
unsafe-make-security-guard-at-root)
|
unsafe-make-security-guard-at-root
|
||||||
|
unsafe-add-post-custodian-shutdown)
|
||||||
(for-syntax racket/base racket/list syntax/stx racket/syntax
|
(for-syntax racket/base racket/list syntax/stx racket/syntax
|
||||||
racket/struct-info))
|
racket/struct-info))
|
||||||
|
|
||||||
|
@ -130,7 +131,8 @@
|
||||||
(define (get-ffi-lib name [version/s ""]
|
(define (get-ffi-lib name [version/s ""]
|
||||||
#:fail [fail #f]
|
#:fail [fail #f]
|
||||||
#:get-lib-dirs [get-lib-dirs get-lib-search-dirs]
|
#:get-lib-dirs [get-lib-dirs get-lib-search-dirs]
|
||||||
#:global? [global? (eq? (system-type 'so-mode) 'global)])
|
#:global? [global? (eq? (system-type 'so-mode) 'global)]
|
||||||
|
#:custodian [custodian #f])
|
||||||
(cond
|
(cond
|
||||||
[(not name) (ffi-lib name)] ; #f => NULL => open this executable
|
[(not name) (ffi-lib name)] ; #f => NULL => open this executable
|
||||||
[(not (or (string? name) (path? name)))
|
[(not (or (string? name) (path? name)))
|
||||||
|
@ -172,6 +174,7 @@
|
||||||
(string-append name0 "." lib-suffix v)
|
(string-append name0 "." lib-suffix v)
|
||||||
(string-append name0 v "." lib-suffix))))
|
(string-append name0 v "." lib-suffix))))
|
||||||
versions)])
|
versions)])
|
||||||
|
(define lib
|
||||||
(or ;; try to look in our library paths first
|
(or ;; try to look in our library paths first
|
||||||
(and (not absolute?)
|
(and (not absolute?)
|
||||||
(ormap (lambda (dir)
|
(ormap (lambda (dir)
|
||||||
|
@ -198,11 +201,21 @@
|
||||||
(cond [(file-exists?/insecure attempt) " (exists)"]
|
(cond [(file-exists?/insecure attempt) " (exists)"]
|
||||||
[else " (no such file)"])]
|
[else " (no such file)"])]
|
||||||
[else " (using OS library search path)"])))))
|
[else " (using OS library search path)"])))))
|
||||||
(if fail
|
(and (not fail)
|
||||||
(fail)
|
|
||||||
(if (pair? names)
|
(if (pair? names)
|
||||||
(ffi-lib (car names) #f global?)
|
(ffi-lib (car names) #f global?)
|
||||||
(ffi-lib name0 #f global?))))))]))
|
(ffi-lib name0 #f global?))))))
|
||||||
|
(cond
|
||||||
|
[lib
|
||||||
|
(when custodian
|
||||||
|
(unsafe-add-post-custodian-shutdown (lambda () (ffi-lib-unload lib))
|
||||||
|
(if (eq? custodian 'place)
|
||||||
|
#f
|
||||||
|
custodian)))
|
||||||
|
lib]
|
||||||
|
[fail
|
||||||
|
(fail)]
|
||||||
|
[else (error 'ffi-lib "internal error; shouldn't get here")]))]))
|
||||||
|
|
||||||
(define (get-ffi-lib-internal x)
|
(define (get-ffi-lib-internal x)
|
||||||
(if (ffi-lib? x) x (get-ffi-lib x)))
|
(if (ffi-lib? x) x (get-ffi-lib x)))
|
||||||
|
|
|
@ -5,7 +5,7 @@ RACKET = ../../bin/racket
|
||||||
SCHEME = scheme
|
SCHEME = scheme
|
||||||
|
|
||||||
# Controls whether Racket layers are built as unsafe:
|
# Controls whether Racket layers are built as unsafe:
|
||||||
UNSAFE_COMP = --unsafe
|
UNSAFE_COMP = # --unsafe
|
||||||
|
|
||||||
# Controls whether compiled code is compressed:
|
# Controls whether compiled code is compressed:
|
||||||
COMPRESS_COMP = # --compress
|
COMPRESS_COMP = # --compress
|
||||||
|
|
|
@ -476,7 +476,7 @@
|
||||||
(1/log-message (|#%app| 1/current-logger) level str #f)))
|
(1/log-message (|#%app| 1/current-logger) level str #f)))
|
||||||
(set-error-display-eprintf! (lambda (fmt . args)
|
(set-error-display-eprintf! (lambda (fmt . args)
|
||||||
(apply 1/fprintf (|#%app| 1/current-error-port) fmt args)))
|
(apply 1/fprintf (|#%app| 1/current-error-port) fmt args)))
|
||||||
(set-ffi-get-lib-and-obj! ffi-get-lib ffi-get-obj ptr->address)
|
(set-ffi-get-lib-and-obj! ffi-get-lib ffi-get-obj ffi-unload-lib ptr->address)
|
||||||
(set-make-async-callback-poll-wakeup! unsafe-make-signal-received)
|
(set-make-async-callback-poll-wakeup! unsafe-make-signal-received)
|
||||||
(set-get-machine-info! get-machine-info)
|
(set-get-machine-info! get-machine-info)
|
||||||
(set-processor-count! (1/processor-count))
|
(set-processor-count! (1/processor-count))
|
||||||
|
|
|
@ -610,7 +610,7 @@
|
||||||
ctype-alignof ctype-basetype ctype-c->scheme ctype-scheme->c ctype-sizeof ctype?
|
ctype-alignof ctype-basetype ctype-c->scheme ctype-scheme->c ctype-sizeof ctype?
|
||||||
end-stubborn-change extflvector->cpointer
|
end-stubborn-change extflvector->cpointer
|
||||||
ffi-call ffi-call-maker ffi-callback ffi-callback-maker ffi-callback?
|
ffi-call ffi-call-maker ffi-callback ffi-callback-maker ffi-callback?
|
||||||
ffi-lib-name ffi-lib? ffi-obj ffi-obj-lib
|
ffi-lib-name ffi-lib? ffi-obj ffi-obj-lib ffi-lib-unload
|
||||||
ffi-obj-name ffi-obj? flvector->cpointer free free-immobile-cell lookup-errno
|
ffi-obj-name ffi-obj? flvector->cpointer free free-immobile-cell lookup-errno
|
||||||
make-array-type make-cstruct-type make-ctype make-late-weak-box make-late-weak-hasheq
|
make-array-type make-cstruct-type make-ctype make-late-weak-box make-late-weak-hasheq
|
||||||
make-sized-byte-string make-union-type malloc malloc-immobile-cell
|
make-sized-byte-string make-union-type malloc malloc-immobile-cell
|
||||||
|
|
|
@ -748,6 +748,10 @@
|
||||||
(lambda (h)
|
(lambda (h)
|
||||||
(make-ffi-lib h name))))]))
|
(make-ffi-lib h name))))]))
|
||||||
|
|
||||||
|
(define/who (ffi-lib-unload lib)
|
||||||
|
(check who ffi-lib? lib)
|
||||||
|
(ffi-unload-lib (ffi-lib-handle lib)))
|
||||||
|
|
||||||
(define-record-type (cpointer/ffi-obj make-ffi-obj ffi-obj?)
|
(define-record-type (cpointer/ffi-obj make-ffi-obj ffi-obj?)
|
||||||
(parent cpointer)
|
(parent cpointer)
|
||||||
(fields lib name))
|
(fields lib name))
|
||||||
|
@ -777,6 +781,11 @@
|
||||||
#f
|
#f
|
||||||
(success-k #f))))
|
(success-k #f))))
|
||||||
|
|
||||||
|
(define ffi-unload-lib
|
||||||
|
;; Placeholder implementation that does nothing:
|
||||||
|
(lambda (lib)
|
||||||
|
(void)))
|
||||||
|
|
||||||
(define ffi-get-obj
|
(define ffi-get-obj
|
||||||
;; Placeholder implementation that always fails:
|
;; Placeholder implementation that always fails:
|
||||||
(lambda (who lib lib-name name success-k)
|
(lambda (who lib lib-name name success-k)
|
||||||
|
@ -790,9 +799,10 @@
|
||||||
;; Placeholder implementation
|
;; Placeholder implementation
|
||||||
(lambda (p) p))
|
(lambda (p) p))
|
||||||
|
|
||||||
(define (set-ffi-get-lib-and-obj! do-ffi-get-lib do-ffi-get-obj do-ffi-ptr->address)
|
(define (set-ffi-get-lib-and-obj! do-ffi-get-lib do-ffi-get-obj do-ffi-unload-lib do-ffi-ptr->address)
|
||||||
(set! ffi-get-lib do-ffi-get-lib)
|
(set! ffi-get-lib do-ffi-get-lib)
|
||||||
(set! ffi-get-obj do-ffi-get-obj)
|
(set! ffi-get-obj do-ffi-get-obj)
|
||||||
|
(set! ffi-unload-lib do-ffi-unload-lib)
|
||||||
(set! ffi-ptr->address do-ffi-ptr->address))
|
(set! ffi-ptr->address do-ffi-ptr->address))
|
||||||
|
|
||||||
;; ----------------------------------------
|
;; ----------------------------------------
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
"../locale/string.rkt")
|
"../locale/string.rkt")
|
||||||
|
|
||||||
(provide ffi-get-lib
|
(provide ffi-get-lib
|
||||||
ffi-lib-unload
|
ffi-unload-lib
|
||||||
ffi-get-obj
|
ffi-get-obj
|
||||||
current-load-extension)
|
current-load-extension)
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
(raise-dll-error who msg err-str dll)])]
|
(raise-dll-error who msg err-str dll)])]
|
||||||
[else (success-k dll)]))
|
[else (success-k dll)]))
|
||||||
|
|
||||||
(define/who (ffi-lib-unload dll)
|
(define/who (ffi-unload-lib dll)
|
||||||
(start-atomic)
|
(start-atomic)
|
||||||
(define r (rktio_dll_close rktio dll))
|
(define r (rktio_dll_close rktio dll))
|
||||||
(cond
|
(cond
|
||||||
|
|
|
@ -251,7 +251,6 @@ typedef struct Thread_Local_Variables {
|
||||||
intptr_t scheme_current_cont_mark_pos_;
|
intptr_t scheme_current_cont_mark_pos_;
|
||||||
struct Scheme_Custodian *main_custodian_;
|
struct Scheme_Custodian *main_custodian_;
|
||||||
struct Scheme_Hash_Table *limited_custodians_;
|
struct Scheme_Hash_Table *limited_custodians_;
|
||||||
struct Scheme_Object *post_custodian_shutdowns_;
|
|
||||||
struct Scheme_Plumber *initial_plumber_;
|
struct Scheme_Plumber *initial_plumber_;
|
||||||
struct Scheme_Config *initial_config_;
|
struct Scheme_Config *initial_config_;
|
||||||
struct Scheme_Thread *swap_target_;
|
struct Scheme_Thread *swap_target_;
|
||||||
|
@ -639,7 +638,6 @@ XFORM_GC_VARIABLE_STACK_THROUGH_THREAD_LOCAL;
|
||||||
#define main_custodian XOA (scheme_get_thread_local_variables()->main_custodian_)
|
#define main_custodian XOA (scheme_get_thread_local_variables()->main_custodian_)
|
||||||
#define last_custodian XOA (scheme_get_thread_local_variables()->last_custodian_)
|
#define last_custodian XOA (scheme_get_thread_local_variables()->last_custodian_)
|
||||||
#define limited_custodians XOA (scheme_get_thread_local_variables()->limited_custodians_)
|
#define limited_custodians XOA (scheme_get_thread_local_variables()->limited_custodians_)
|
||||||
#define post_custodian_shutdowns XOA (scheme_get_thread_local_variables()->post_custodian_shutdowns_)
|
|
||||||
#define initial_plumber XOA (scheme_get_thread_local_variables()->initial_plumber_)
|
#define initial_plumber XOA (scheme_get_thread_local_variables()->initial_plumber_)
|
||||||
#define initial_config XOA (scheme_get_thread_local_variables()->initial_config_)
|
#define initial_config XOA (scheme_get_thread_local_variables()->initial_config_)
|
||||||
#define swap_target XOA (scheme_get_thread_local_variables()->swap_target_)
|
#define swap_target XOA (scheme_get_thread_local_variables()->swap_target_)
|
||||||
|
|
|
@ -571,8 +571,6 @@ void scheme_place_instance_destroy(int force)
|
||||||
else
|
else
|
||||||
scheme_run_atexit_closers_on_all(force_more_closed_after);
|
scheme_run_atexit_closers_on_all(force_more_closed_after);
|
||||||
|
|
||||||
scheme_run_post_custodian_shutdown();
|
|
||||||
|
|
||||||
scheme_release_fd_semaphores();
|
scheme_release_fd_semaphores();
|
||||||
|
|
||||||
scheme_release_file_descriptor();
|
scheme_release_file_descriptor();
|
||||||
|
|
|
@ -156,6 +156,7 @@ static int mark_custodian_val_MARK(void *p, struct NewGC *gc) {
|
||||||
gcMARK2(m->closers, gc);
|
gcMARK2(m->closers, gc);
|
||||||
gcMARK2(m->data, gc);
|
gcMARK2(m->data, gc);
|
||||||
gcMARK2(m->data_ptr, gc);
|
gcMARK2(m->data_ptr, gc);
|
||||||
|
gcMARK2(m->post_callbacks, gc);
|
||||||
|
|
||||||
gcMARK2(m->parent, gc);
|
gcMARK2(m->parent, gc);
|
||||||
gcMARK2(m->sibling, gc);
|
gcMARK2(m->sibling, gc);
|
||||||
|
@ -184,6 +185,7 @@ static int mark_custodian_val_FIXUP(void *p, struct NewGC *gc) {
|
||||||
gcFIXUP2(m->closers, gc);
|
gcFIXUP2(m->closers, gc);
|
||||||
gcFIXUP2(m->data, gc);
|
gcFIXUP2(m->data, gc);
|
||||||
gcFIXUP2(m->data_ptr, gc);
|
gcFIXUP2(m->data_ptr, gc);
|
||||||
|
gcFIXUP2(m->post_callbacks, gc);
|
||||||
|
|
||||||
gcFIXUP2(m->parent, gc);
|
gcFIXUP2(m->parent, gc);
|
||||||
gcFIXUP2(m->sibling, gc);
|
gcFIXUP2(m->sibling, gc);
|
||||||
|
|
|
@ -1691,6 +1691,7 @@ mark_custodian_val {
|
||||||
gcMARK2(m->closers, gc);
|
gcMARK2(m->closers, gc);
|
||||||
gcMARK2(m->data, gc);
|
gcMARK2(m->data, gc);
|
||||||
gcMARK2(m->data_ptr, gc);
|
gcMARK2(m->data_ptr, gc);
|
||||||
|
gcMARK2(m->post_callbacks, gc);
|
||||||
|
|
||||||
gcMARK2(m->parent, gc);
|
gcMARK2(m->parent, gc);
|
||||||
gcMARK2(m->sibling, gc);
|
gcMARK2(m->sibling, gc);
|
||||||
|
|
|
@ -850,6 +850,7 @@ struct Scheme_Custodian {
|
||||||
Scheme_Close_Custodian_Client **closers;
|
Scheme_Close_Custodian_Client **closers;
|
||||||
void **data;
|
void **data;
|
||||||
void ***data_ptr; /* points to `data`, registered as finalizer data for strong retention */
|
void ***data_ptr; /* points to `data`, registered as finalizer data for strong retention */
|
||||||
|
Scheme_Object *post_callbacks; /* additional callbacks run after all others */
|
||||||
|
|
||||||
/* weak indirections: */
|
/* weak indirections: */
|
||||||
Scheme_Custodian_Reference *parent;
|
Scheme_Custodian_Reference *parent;
|
||||||
|
@ -877,7 +878,6 @@ Scheme_Thread *scheme_do_close_managed(Scheme_Custodian *m, Scheme_Exit_Closer_F
|
||||||
Scheme_Custodian *scheme_get_current_custodian(void);
|
Scheme_Custodian *scheme_get_current_custodian(void);
|
||||||
void scheme_run_atexit_closers_on_all(Scheme_Exit_Closer_Func alt);
|
void scheme_run_atexit_closers_on_all(Scheme_Exit_Closer_Func alt);
|
||||||
void scheme_run_atexit_closers(Scheme_Object *o, Scheme_Close_Custodian_Client *f, void *data);
|
void scheme_run_atexit_closers(Scheme_Object *o, Scheme_Close_Custodian_Client *f, void *data);
|
||||||
void scheme_run_post_custodian_shutdown();
|
|
||||||
|
|
||||||
typedef struct Scheme_Security_Guard {
|
typedef struct Scheme_Security_Guard {
|
||||||
Scheme_Object so;
|
Scheme_Object so;
|
||||||
|
|
|
@ -650,7 +650,7 @@ scheme_init_unsafe_thread (Scheme_Startup_Env *env)
|
||||||
ADD_PRIM_W_ARITY("unsafe-custodian-register", unsafe_custodian_register, 5, 5, env);
|
ADD_PRIM_W_ARITY("unsafe-custodian-register", unsafe_custodian_register, 5, 5, env);
|
||||||
ADD_PRIM_W_ARITY("unsafe-custodian-unregister", unsafe_custodian_unregister, 2, 2, env);
|
ADD_PRIM_W_ARITY("unsafe-custodian-unregister", unsafe_custodian_unregister, 2, 2, env);
|
||||||
|
|
||||||
ADD_PRIM_W_ARITY("unsafe-add-post-custodian-shutdown", unsafe_add_post_custodian_shutdown, 1, 1, env);
|
ADD_PRIM_W_ARITY("unsafe-add-post-custodian-shutdown", unsafe_add_post_custodian_shutdown, 1, 2, env);
|
||||||
|
|
||||||
ADD_PRIM_W_ARITY("unsafe-register-process-global", unsafe_register_process_global, 2, 2, env);
|
ADD_PRIM_W_ARITY("unsafe-register-process-global", unsafe_register_process_global, 2, 2, env);
|
||||||
ADD_PRIM_W_ARITY("unsafe-get-place-table", unsafe_get_place_table, 0, 0, env);
|
ADD_PRIM_W_ARITY("unsafe-get-place-table", unsafe_get_place_table, 0, 0, env);
|
||||||
|
@ -1236,6 +1236,8 @@ Scheme_Custodian *scheme_make_custodian(Scheme_Custodian *parent)
|
||||||
data_ptr = (void ***)scheme_malloc(sizeof(void**));
|
data_ptr = (void ***)scheme_malloc(sizeof(void**));
|
||||||
m->data_ptr = data_ptr;
|
m->data_ptr = data_ptr;
|
||||||
|
|
||||||
|
m->post_callbacks = scheme_null;
|
||||||
|
|
||||||
insert_custodian(m, parent);
|
insert_custodian(m, parent);
|
||||||
|
|
||||||
scheme_add_finalizer(m, do_adjust_custodian_family, data_ptr);
|
scheme_add_finalizer(m, do_adjust_custodian_family, data_ptr);
|
||||||
|
@ -1553,6 +1555,17 @@ Scheme_Thread *scheme_do_close_managed(Scheme_Custodian *m, Scheme_Exit_Closer_F
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (SCHEME_PAIRP(m->post_callbacks)) {
|
||||||
|
Scheme_Object *proc;
|
||||||
|
scheme_start_in_scheduler();
|
||||||
|
while (SCHEME_PAIRP(m->post_callbacks)) {
|
||||||
|
proc = SCHEME_CAR(m->post_callbacks);
|
||||||
|
m->post_callbacks = SCHEME_CDR(m->post_callbacks);
|
||||||
|
_scheme_apply_multi(proc, 0, NULL);
|
||||||
|
}
|
||||||
|
scheme_end_in_scheduler();
|
||||||
|
}
|
||||||
|
|
||||||
m->count = 0;
|
m->count = 0;
|
||||||
m->alloc = 0;
|
m->alloc = 0;
|
||||||
m->elems = 0;
|
m->elems = 0;
|
||||||
|
@ -1950,38 +1963,33 @@ void do_run_atexit_closers_on_all()
|
||||||
|
|
||||||
static Scheme_Object *unsafe_add_post_custodian_shutdown(int argc, Scheme_Object *argv[])
|
static Scheme_Object *unsafe_add_post_custodian_shutdown(int argc, Scheme_Object *argv[])
|
||||||
{
|
{
|
||||||
|
Scheme_Custodian *c;
|
||||||
|
Scheme_Object *l;
|
||||||
|
|
||||||
scheme_check_proc_arity("unsafe-add-post-custodian-shutdown", 0, 0, argc, argv);
|
scheme_check_proc_arity("unsafe-add-post-custodian-shutdown", 0, 0, argc, argv);
|
||||||
|
|
||||||
#if defined(MZ_USE_PLACES)
|
if ((argc > 1)
|
||||||
if (!RUNNING_IN_ORIGINAL_PLACE) {
|
&& !(SCHEME_FALSEP(argv[1])
|
||||||
if (!post_custodian_shutdowns) {
|
|| SCHEME_CUSTODIANP(argv[1])))
|
||||||
REGISTER_SO(post_custodian_shutdowns);
|
scheme_wrong_contract("unsafe-add-post-custodian-shutdown", "custodian?", 1, argc, argv);
|
||||||
post_custodian_shutdowns = scheme_null;
|
|
||||||
}
|
|
||||||
|
|
||||||
post_custodian_shutdowns = scheme_make_pair(argv[0], post_custodian_shutdowns);
|
if ((argc > 1) && !SCHEME_FALSEP(argv[1]))
|
||||||
}
|
c = (Scheme_Custodian *)argv[1];
|
||||||
|
else
|
||||||
|
c = main_custodian;
|
||||||
|
|
||||||
|
#if defined(MZ_USE_PLACES)
|
||||||
|
if (RUNNING_IN_ORIGINAL_PLACE
|
||||||
|
&& (c == main_custodian))
|
||||||
|
return scheme_void;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
l = scheme_make_pair(argv[0], c->post_callbacks);
|
||||||
|
c->post_callbacks = l;
|
||||||
|
|
||||||
return scheme_void;
|
return scheme_void;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scheme_run_post_custodian_shutdown()
|
|
||||||
{
|
|
||||||
#if defined(MZ_USE_PLACES)
|
|
||||||
if (post_custodian_shutdowns) {
|
|
||||||
Scheme_Object *proc;
|
|
||||||
scheme_start_in_scheduler();
|
|
||||||
while (SCHEME_PAIRP(post_custodian_shutdowns)) {
|
|
||||||
proc = SCHEME_CAR(post_custodian_shutdowns);
|
|
||||||
post_custodian_shutdowns = SCHEME_CDR(post_custodian_shutdowns);
|
|
||||||
_scheme_apply_multi(proc, 0, NULL);
|
|
||||||
}
|
|
||||||
scheme_end_in_scheduler();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void scheme_set_atexit(Scheme_At_Exit_Proc p)
|
void scheme_set_atexit(Scheme_At_Exit_Proc p)
|
||||||
{
|
{
|
||||||
replacement_at_exit = p;
|
replacement_at_exit = p;
|
||||||
|
|
|
@ -139,6 +139,9 @@ rktio_ok_t rktio_dll_close(rktio_t *rktio, rktio_dll_t *dll)
|
||||||
{
|
{
|
||||||
int ok = 1;
|
int ok = 1;
|
||||||
|
|
||||||
|
if (!dll->name)
|
||||||
|
return ok;
|
||||||
|
|
||||||
dll->refcount--;
|
dll->refcount--;
|
||||||
if (dll->refcount)
|
if (dll->refcount)
|
||||||
return ok;
|
return ok;
|
||||||
|
|
|
@ -22,7 +22,8 @@
|
||||||
[gc-roots #:mutable] ; weak references to charge to custodian; access without interrupts
|
[gc-roots #:mutable] ; weak references to charge to custodian; access without interrupts
|
||||||
[memory-limits #:mutable] ; list of (cons limit cust)
|
[memory-limits #:mutable] ; list of (cons limit cust)
|
||||||
[immediate-limit #:mutable] ; limit on immediate allocation
|
[immediate-limit #:mutable] ; limit on immediate allocation
|
||||||
[sync-futures? #:mutable]) ; whether a sync witht future threads is needed on shutdown
|
[sync-futures? #:mutable] ; whether a sync witht future threads is needed on shutdown
|
||||||
|
[post-shutdown #:mutable]) ; callbacks to run in atomic mode after shutdown
|
||||||
#:authentic)
|
#:authentic)
|
||||||
|
|
||||||
(define (create-custodian parent)
|
(define (create-custodian parent)
|
||||||
|
@ -37,7 +38,8 @@
|
||||||
#f ; GC roots
|
#f ; GC roots
|
||||||
null ; memory limits
|
null ; memory limits
|
||||||
#f ; immediate limit
|
#f ; immediate limit
|
||||||
#f)) ; sync-futures?
|
#f ; sync-futures?
|
||||||
|
null)) ; post-shutdown
|
||||||
|
|
||||||
;; Call only from a place's main pthread, and only a
|
;; Call only from a place's main pthread, and only a
|
||||||
;; place's main thread should change the box value.
|
;; place's main thread should change the box value.
|
||||||
|
|
|
@ -33,9 +33,10 @@
|
||||||
custodian-register-thread
|
custodian-register-thread
|
||||||
custodian-register-place
|
custodian-register-place
|
||||||
raise-custodian-is-shut-down
|
raise-custodian-is-shut-down
|
||||||
set-post-shutdown-action!
|
unsafe-add-post-custodian-shutdown
|
||||||
check-queued-custodian-shutdown
|
check-queued-custodian-shutdown
|
||||||
set-place-custodian-procs!
|
set-place-custodian-procs!
|
||||||
|
set-post-shutdown-action!
|
||||||
custodian-check-immediate-limit)
|
custodian-check-immediate-limit)
|
||||||
|
|
||||||
(module+ scheduling
|
(module+ scheduling
|
||||||
|
@ -186,6 +187,10 @@
|
||||||
(when self-ref
|
(when self-ref
|
||||||
(set-custodian-reference-c! self-ref (custodian-self-reference parent)))
|
(set-custodian-reference-c! self-ref (custodian-self-reference parent)))
|
||||||
(hash-clear! (custodian-children c))
|
(hash-clear! (custodian-children c))
|
||||||
|
(set-custodian-post-shutdown! parent
|
||||||
|
(append (custodian-post-shutdown c)
|
||||||
|
(custodian-post-shutdown parent)))
|
||||||
|
(set-custodian-post-shutdown! c null)
|
||||||
(when gc-roots (hash-clear! gc-roots))))
|
(when gc-roots (hash-clear! gc-roots))))
|
||||||
|
|
||||||
;; Called in scheduler thread:
|
;; Called in scheduler thread:
|
||||||
|
@ -274,6 +279,9 @@
|
||||||
(callback child c)
|
(callback child c)
|
||||||
(callback child)))
|
(callback child)))
|
||||||
(hash-clear! (custodian-children c))
|
(hash-clear! (custodian-children c))
|
||||||
|
(for ([proc (in-list (custodian-post-shutdown c))])
|
||||||
|
(proc))
|
||||||
|
(set-custodian-post-shutdown! c null)
|
||||||
(let ([sema (custodian-shutdown-sema c)])
|
(let ([sema (custodian-shutdown-sema c)])
|
||||||
(when sema
|
(when sema
|
||||||
(semaphore-post-all sema)))
|
(semaphore-post-all sema)))
|
||||||
|
@ -291,6 +299,15 @@
|
||||||
(semaphore-post-all sema))
|
(semaphore-post-all sema))
|
||||||
sema))))
|
sema))))
|
||||||
|
|
||||||
|
(define/who (unsafe-add-post-custodian-shutdown proc [custodian #f])
|
||||||
|
(check who (procedure-arity-includes/c 0) proc)
|
||||||
|
(check who custodian? #:or-false custodian)
|
||||||
|
(define c (or custodian (place-custodian current-place)))
|
||||||
|
(unless (and (not (place-parent current-place))
|
||||||
|
(eq? c (place-custodian current-place)))
|
||||||
|
(atomically
|
||||||
|
(set-custodian-post-shutdown! c (cons proc (custodian-post-shutdown c))))))
|
||||||
|
|
||||||
(define (custodian-subordinate? c super-c)
|
(define (custodian-subordinate? c super-c)
|
||||||
(let loop ([p-cref (custodian-parent-reference c)])
|
(let loop ([p-cref (custodian-parent-reference c)])
|
||||||
(define p (and p-cref (custodian-reference->custodian p-cref)))
|
(define p (and p-cref (custodian-reference->custodian p-cref)))
|
||||||
|
|
|
@ -34,8 +34,7 @@
|
||||||
place-channel-put
|
place-channel-put
|
||||||
|
|
||||||
set-make-place-ports+fds!
|
set-make-place-ports+fds!
|
||||||
place-pumper-threads
|
place-pumper-threads)
|
||||||
unsafe-add-post-custodian-shutdown)
|
|
||||||
|
|
||||||
;; For `(struct place ...)`, see "place-object.rkt"
|
;; For `(struct place ...)`, see "place-object.rkt"
|
||||||
|
|
||||||
|
@ -441,13 +440,6 @@
|
||||||
(define (place-pumper-threads p vec)
|
(define (place-pumper-threads p vec)
|
||||||
(set-place-pumpers! p vec))
|
(set-place-pumpers! p vec))
|
||||||
|
|
||||||
(define (unsafe-add-post-custodian-shutdown proc)
|
|
||||||
(when (place-parent current-place)
|
|
||||||
(atomically
|
|
||||||
(set-place-post-shutdown! current-place
|
|
||||||
(cons proc
|
|
||||||
(place-post-shutdown current-place))))))
|
|
||||||
|
|
||||||
(void (set-place-custodian-procs!
|
(void (set-place-custodian-procs!
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(atomically (ensure-wakeup-handle!))
|
(atomically (ensure-wakeup-handle!))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user