From 2768499b883ec0bdaffbd73fc0cf1bdd001c0d7b Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Tue, 9 Jun 2020 10:04:46 -0600 Subject: [PATCH] fix rktio destroy to release a pipe used for internal singals Also, fix CS to desstroy a place's rktio instance when the place exits. Closes #3243 --- pkgs/racket-test-extra/tests/racket/many-places.rkt | 10 ++++++++++ racket/src/cs/main.sps | 3 +++ racket/src/cs/rumble.sls | 1 + racket/src/cs/rumble/place.ss | 7 ++++++- racket/src/io/host/rktio.rkt | 7 ++++++- racket/src/io/main.rkt | 9 ++++++++- racket/src/io/port/place.rkt | 6 +++--- racket/src/rktio/rktio_main.c | 1 + racket/src/rktio/rktio_poll_set.c | 12 ++++++++++++ racket/src/rktio/rktio_private.h | 1 + 10 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 pkgs/racket-test-extra/tests/racket/many-places.rkt diff --git a/pkgs/racket-test-extra/tests/racket/many-places.rkt b/pkgs/racket-test-extra/tests/racket/many-places.rkt new file mode 100644 index 0000000000..49806977b9 --- /dev/null +++ b/pkgs/racket-test-extra/tests/racket/many-places.rkt @@ -0,0 +1,10 @@ +#lang racket/base +(require racket/place) + +;; Try to catch a resource leak starting and finishing places. + +(for ([i (in-range 256)]) + (printf "~s\n" i) + (map place-wait + (for/list ([i 4]) + (dynamic-place ''#%kernel 'list)))) diff --git a/racket/src/cs/main.sps b/racket/src/cs/main.sps index 6ae57bf862..8e0c77aab6 100644 --- a/racket/src/cs/main.sps +++ b/racket/src/cs/main.sps @@ -818,6 +818,9 @@ (lambda () (let ([f (dynamic-require mod sym)]) (f pch))))) + (set-destroy-place! + (lambda () + (io-place-destroy!))) (let ([a (or addon-dir (getenv-bytes "PLTADDONDIR"))]) diff --git a/racket/src/cs/rumble.sls b/racket/src/cs/rumble.sls index 0e7bf81bf1..1123caa0c1 100644 --- a/racket/src/cs/rumble.sls +++ b/racket/src/cs/rumble.sls @@ -600,6 +600,7 @@ unsafe-extflvector-length unsafe-extflvector-ref unsafe-extflvector-set! set-start-place! ; not exported to Racket + set-destroy-place! ; not exported to Racket fork-place ; not exported to Racket start-place ; not exported to Racket place-enabled? diff --git a/racket/src/cs/rumble/place.ss b/racket/src/cs/rumble/place.ss index f59d5f097f..f2ff07327e 100644 --- a/racket/src/cs/rumble/place.ss +++ b/racket/src/cs/rumble/place.ss @@ -91,7 +91,8 @@ (set-box! place-esc-box esc) (thunk) 0))]) - (finish-proc result))))) + (finish-proc result) + (do-destroy-place))))) ;; Must be called within an engine, used for memory accounting: (define (current-place-roots) (list (place-registers) @@ -105,6 +106,10 @@ (define (set-start-place! proc) (set! do-start-place proc)) +(define do-destroy-place void) +(define (set-destroy-place! proc) + (set! do-destroy-place proc)) + (define (start-place pch path sym in out err cust plumber) (let ([finish (do-start-place pch path sym in out err cust plumber)]) (reset-async-callback-poll-wakeup!) diff --git a/racket/src/io/host/rktio.rkt b/racket/src/io/host/rktio.rkt index 04144bcbc0..373563f110 100644 --- a/racket/src/io/host/rktio.rkt +++ b/racket/src/io/host/rktio.rkt @@ -10,7 +10,8 @@ rktio-errno rktio-errstep racket-error? - rktio-place-init!) + rktio-place-init! + rktio-place-destroy!) ;; More `provide`s added by macros below (define rktio-table @@ -82,5 +83,9 @@ (define (rktio-place-init!) (set! rktio (rktio_init))) +(define (rktio-place-destroy!) + (rktio_destroy rktio) + (set! rktio #f)) + ;; Only in the main place: (void (rktio_do_install_os_signal_handler rktio)) diff --git a/racket/src/io/main.rkt b/racket/src/io/main.rkt index 9dbc73d0c6..9566966c20 100644 --- a/racket/src/io/main.rkt +++ b/racket/src/io/main.rkt @@ -25,7 +25,8 @@ "port/parameter.rkt" "path/system.rkt" (only-in "host/rktio.rkt" - rktio-place-init!) + rktio-place-init! + rktio-place-destroy!) (submod "error/main.rkt" place-init) (only-in "sandman/ltps.rkt" @@ -58,6 +59,7 @@ (all-from-out "run/main.rkt") make-place-ports+fds io-place-init! + io-place-destroy! get-original-error-port) (define (io-place-init! in-fd out-fd err-fd cust plumber) @@ -68,3 +70,8 @@ (install-error-value->string-handler!) (init-current-directory!) (init-current-ports! in-fd out-fd err-fd cust plumber)) + +(define (io-place-destroy!) + ;; We expect everything based on rktio to be destroyed at this point + ;; via custodian shutdown + (rktio-place-destroy!)) diff --git a/racket/src/io/port/place.rkt b/racket/src/io/port/place.rkt index 1dae3827b6..f1e40fa7a8 100644 --- a/racket/src/io/port/place.rkt +++ b/racket/src/io/port/place.rkt @@ -17,7 +17,7 @@ (values #f (dup-fd (fd-port-fd in) void "stdin dup")) (reverse-pipe void "stdin pipe"))) (define (clean-in) - (rktio_close child-in-fd) + (rktio_close rktio child-in-fd) (unless in (rktio_close rktio parent-in-fd))) (define-values (parent-out-fd child-out-fd) @@ -25,9 +25,9 @@ (values #f (dup-fd (fd-port-fd out) clean-in "stdout dup")) (pipe clean-in "stdout pipe"))) (define (clean-out+in) - (rktio_close child-out-fd) + (rktio_close rktio child-out-fd) (unless out - (rktio_close parent-out-fd)) + (rktio_close rktio parent-out-fd)) (clean-in)) (define-values (parent-err-fd child-err-fd) (if err diff --git a/racket/src/rktio/rktio_main.c b/racket/src/rktio/rktio_main.c index d56919595c..a239532fda 100644 --- a/racket/src/rktio/rktio_main.c +++ b/racket/src/rktio/rktio_main.c @@ -72,6 +72,7 @@ void rktio_destroy(rktio_t *rktio) rktio_free_ghbn(rktio); rktio_free_global_poll_set(rktio); rktio_stop_fs_change(rktio); + rktio_free_signal(rktio); #ifdef RKTIO_SYSTEM_WINDOWS rktio_winsock_done(rktio); #endif diff --git a/racket/src/rktio/rktio_poll_set.c b/racket/src/rktio/rktio_poll_set.c index adf68d3114..ce73f86c7a 100644 --- a/racket/src/rktio/rktio_poll_set.c +++ b/racket/src/rktio/rktio_poll_set.c @@ -1127,6 +1127,18 @@ int rktio_initialize_signal(rktio_t *rktio) #endif } +void rktio_free_signal(rktio_t *rktio) +{ +#ifdef RKTIO_SYSTEM_UNIX + rktio_reliably_close(rktio->external_event_fd); + rktio_reliably_close(rktio->put_external_event_fd); +#endif + +#ifdef RKTIO_SYSTEM_WINDOWS + CloseHandle(rktio->break_semaphore); +#endif +} + rktio_signal_handle_t *rktio_get_signal_handle(rktio_t *rktio) { #ifdef RKTIO_SYSTEM_UNIX diff --git a/racket/src/rktio/rktio_private.h b/racket/src/rktio/rktio_private.h index fec026ec3e..6b91d12d34 100644 --- a/racket/src/rktio/rktio_private.h +++ b/racket/src/rktio/rktio_private.h @@ -141,6 +141,7 @@ struct rktio_t { void rktio_alloc_global_poll_set(rktio_t *rktio); void rktio_free_global_poll_set(rktio_t *rktio); int rktio_initialize_signal(rktio_t *rktio); +void rktio_free_signal(rktio_t *rktio); #ifdef USE_FAR_RKTIO_FDCALLS