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 void add_child_status(int pid, int status) { Child_Status *st; /* Search for existing record, which will have a signal_fd: */ pthread_mutex_lock(&child_status_lock); for (st = child_statuses; st; st = st->next) { if (st->pid == pid) break; } if (!st) { /* must have terminated before it was registered (and since we detected it, it must not be in a group) */ st = malloc(sizeof(Child_Status)); st->pid = pid; st->signal_fd = NULL; st->next = child_statuses; child_statuses = st; st->next_unused = NULL; st->unneeded = 0; st->in_group = 0; } st->status = status; st->done = 1; if (st->signal_fd && st->in_group) remove_group_signal_fd(st->signal_fd); pthread_mutex_unlock(&child_status_lock); if (st->signal_fd) rktio_signal_received_at(st->signal_fd); if (st->unneeded) (void)centralized_get_child_status(st->pid, 0, 0, NULL); }
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 }