From a17516f5b6bdbcb0a88345961fd3917346fab184 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Mon, 9 Nov 2020 09:23:06 -0700 Subject: [PATCH] rktio: repair for subprocesses on Unix witthout threads A list of pending process records was not managed correctly when interest in a subprocess is abandoned before the subprocess completes. --- .../tests/racket/subprocess.rktl | 15 ++++++++++++++ racket/src/rktio/rktio_process.c | 20 +++++++++++++++---- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/pkgs/racket-test-core/tests/racket/subprocess.rktl b/pkgs/racket-test-core/tests/racket/subprocess.rktl index e73347cf8f..0d399c87b7 100644 --- a/pkgs/racket-test-core/tests/racket/subprocess.rktl +++ b/pkgs/racket-test-core/tests/racket/subprocess.rktl @@ -662,6 +662,21 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Check for cleaning up a subprocess without waiting for it to complete: +(for ([j 10]) + (for-each + (lambda (f) (f)) + (for/list ([i 10]) + (define-values (sp o i e) (subprocess #f #f #f cat)) + (subprocess-kill sp 'kill) + (lambda () + (close-output-port i) + (close-input-port o) + (close-input-port e)))) + (collect-garbage)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + (for ([f (list tmpfile tmpfile2)] #:when (file-exists? f)) (delete-file f)) diff --git a/racket/src/rktio/rktio_process.c b/racket/src/rktio/rktio_process.c index 5820f6554c..be17d7aa2a 100644 --- a/racket/src/rktio/rktio_process.c +++ b/racket/src/rktio/rktio_process.c @@ -602,7 +602,6 @@ static void init_sigchld(rktio_t *rktio) #endif } -#if !defined(CENTRALIZED_SIGCHILD) static void remove_from_sigchld_chain(rktio_t *rktio) { if (rktio->in_sigchld_chain) { @@ -620,7 +619,6 @@ static void remove_from_sigchld_chain(rktio_t *rktio) } } } -#endif static void check_child_done(rktio_t *rktio, pid_t pid) { @@ -948,14 +946,25 @@ void rktio_process_forget(rktio_t *rktio, rktio_process_t *sp) centralized_ended_child(); } # else - if (!((System_Child *)sp->handle)->done) { + System_Child *sc = (System_Child *)sp->handle, *sc2, *prev; + if (!sc->done) { void **unused_pid; unused_pid = malloc(sizeof(void *) * 2); unused_pid[0] = (void *)(intptr_t)sp->pid; unused_pid[1] = unused_pids; rktio->need_to_check_children = 1; + + prev = NULL; + for (sc2 = rktio->system_children; sc2; prev = sc2, sc2 = sc2->next) { + if (sc2 == sc) { + if (prev) + prev->next = sc->next; + else + rktio->system_children = sc->next; + } + } } - free(sp->handle); + free(sc); # endif #endif @@ -1457,6 +1466,9 @@ rktio_process_result_t *rktio_process(rktio_t *rktio, if (env) free(env); free(new_argv); +#if !defined(CENTRALIZED_SIGCHILD) + free(sc); +#endif return NULL;