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.
This commit is contained in:
Matthew Flatt 2020-11-09 09:23:06 -07:00
parent a0375111a3
commit a17516f5b6
2 changed files with 31 additions and 4 deletions

View File

@ -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))

View File

@ -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;