void rktio_reap_processes(rktio_t *rktio) { if (rktio->need_to_check_children) { rktio->need_to_check_children = 0; check_child_done(rktio, 0); } }
rktio_status_t *rktio_process_status(rktio_t *rktio, rktio_process_t *sp) { int going = 0, status = 0; rktio_status_t *result; #if defined(RKTIO_SYSTEM_UNIX) # if defined(CENTRALIZED_SIGCHILD) if (sp->done) { status = sp->status; } else { if (!centralized_get_child_status(sp->pid, sp->in_group, 1, &status)) { going = 1; } else { sp->done = 1; sp->status = status; centralized_ended_child(); } } # else System_Child *sc = (System_Child *)sp->handle; check_child_done(rktio, sp->pid); if (sc->done) { status = sc->status; } else going = 1; # endif #else # ifdef RKTIO_SYSTEM_WINDOWS DWORD w; if (sp->handle) { if (GetExitCodeProcess((HANDLE)sp->handle, &w)) { collect_process_time(rktio, w, sp); if (w == STILL_ACTIVE) going = 1; else status = w; } else { get_windows_error(); return NULL; } } else status = -1; # endif #endif result = malloc(sizeof(rktio_status_t)); result->running = going; result->result = (going ? 0 : status); return result; }
int rktio_poll_process_done(rktio_t *rktio, rktio_process_t *sp) { #if defined(RKTIO_SYSTEM_UNIX) # if defined(CENTRALIZED_SIGCHILD) { int status; if (!sp->done) { if (centralized_get_child_status(sp->pid, sp->in_group, 1, &status)) { sp->done = 1; sp->status = status; centralized_ended_child(); return 1; } return 0; } else return RKTIO_PROCESS_DONE; } # else { System_Child *sc; sc = (System_Child *)sp->handle; /* Check specific pid, in case the child has its own group (either given by us or given to itself): */ check_child_done(rktio, sp->pid); return sc->done; } # endif #endif #ifdef RKTIO_SYSTEM_WINDOWS { HANDLE sci = (HANDLE)sp->handle; DWORD w; if (sci) { if (GetExitCodeProcess(sci, &w)) { collect_process_time(rktio, w, sp); return (w != STILL_ACTIVE); } else return RKTIO_PROCESS_DONE; } else return RKTIO_PROCESS_DONE; get_windows_error(); return RKTIO_PROCESS_ERROR; } #endif }
static int do_subprocess_kill(rktio_t *rktio, rktio_process_t *sp, int as_kill) { #if defined(RKTIO_SYSTEM_UNIX) # if defined(CENTRALIZED_SIGCHILD) { int status; if (sp->done) return 1; centralized_wait_suspend(); /* Don't allow group checking, because we don't want to wait on a group if we haven't already: */ if (centralized_get_child_status(sp->pid, 0, 0, &status)) { sp->status = status; sp->done = 1; centralized_wait_resume(); centralized_ended_child(); return 1; } } # else { System_Child *sc = (System_Child *)sp->handle; /* Don't pass sp->pid, because we don't want to wait on a group if we haven't already: */ check_child_done(rktio, 0); if (sc->done) return 1; } # define centralized_wait_resume() /* empty */ # endif while (1) { if (sp->is_group) { if (!killpg(sp->pid, as_kill ? SIGKILL : SIGINT)) { centralized_wait_resume(); return 1; } } else { if (!kill(sp->pid, as_kill ? SIGKILL : SIGINT)) { centralized_wait_resume(); return 1; } } if (errno != EINTR) break; /* Otherwise we were interrupted. Try `kill' again. */ } get_posix_error(); centralized_wait_resume(); return 0; #endif #if defined(RKTIO_SYSTEM_WINDOWS) if (as_kill || sp->is_group) { DWORD w; if (!sp->handle) return 1; if (!as_kill) { /* must be for a group; we don't care whether the original process is still running */ if (GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, sp->pid)) return 1; } else if (GetExitCodeProcess((HANDLE)sp->handle, &w)) { collect_process_time(rktio, w, sp); if (w != STILL_ACTIVE) return 1; if (TerminateProcess((HANDLE)sp->handle, 1)) return 1; } get_windows_error(); return 0; } else return 1; #endif }
static void check_child_done(rktio_t *rktio, pid_t pid) { pid_t result, check_pid; int status, is_unused; System_Child *sc, *prev; void **unused = (void **)unused_pids, **unused_prev = NULL; if (pid && rktio->need_to_check_children) { rktio->need_to_check_children = 0; check_child_done(rktio, 0); } if (rktio->system_children) { do { if (!pid && unused) { check_pid = (pid_t)(intptr_t)unused[0]; is_unused = 1; } else { check_pid = pid; is_unused = 0; } do { result = waitpid(check_pid, &status, WNOHANG); } while ((result == -1) && (errno == EINTR)); if (result > 0) { if (is_unused) { /* done with an inaccessible group id */ void *next; next = (void **)unused[1]; if (unused_prev) unused_prev[1] = unused[1]; else unused_pids = unused[1]; free(unused); unused = (void **)next; } status = extract_child_status(status); prev = NULL; for (sc = rktio->system_children; sc; prev = sc, sc = sc->next) { if (sc->id == result) { sc->done = 1; sc->status = status; if (prev) { prev->next = sc->next; } else rktio->system_children = sc->next; } } } else { if (is_unused) { unused_prev = unused; unused = unused[1]; } } } while ((result > 0) || is_unused); } }