mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-14 14:03:58 +00:00
Clean up handle_child_status
Now that we only call waitpid() on specific processes, we no longer need to search to find the process returned by waitpid.
This commit is contained in:
parent
261d48367d
commit
e11c3f352f
2 changed files with 29 additions and 59 deletions
84
src/proc.cpp
84
src/proc.cpp
|
@ -269,23 +269,6 @@ static void mark_job_complete(const job_t *j) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Store the status of the process pid that was returned by waitpid.
|
|
||||||
static void mark_process_status(process_t *p, proc_status_t status) {
|
|
||||||
// debug( 0, L"Process %ls %ls", p->argv[0], WIFSTOPPED (status)?L"stopped":(WIFEXITED( status
|
|
||||||
// )?L"exited":(WIFSIGNALED( status )?L"signaled to exit":L"BLARGH")) );
|
|
||||||
p->status = status;
|
|
||||||
|
|
||||||
if (status.stopped()) {
|
|
||||||
p->stopped = 1;
|
|
||||||
} else if (status.signal_exited() || status.normal_exited()) {
|
|
||||||
p->completed = 1;
|
|
||||||
} else {
|
|
||||||
// This should never be reached.
|
|
||||||
p->completed = 1;
|
|
||||||
debug(1, "Process %ld exited abnormally", (long)p->pid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void job_mark_process_as_failed(const std::shared_ptr<job_t> &job, const process_t *failed_proc) {
|
void job_mark_process_as_failed(const std::shared_ptr<job_t> &job, const process_t *failed_proc) {
|
||||||
// The given process failed to even lift off (e.g. posix_spawn failed) and so doesn't have a
|
// The given process failed to even lift off (e.g. posix_spawn failed) and so doesn't have a
|
||||||
// valid pid. Mark it and everything after it as dead.
|
// valid pid. Mark it and everything after it as dead.
|
||||||
|
@ -298,46 +281,33 @@ void job_mark_process_as_failed(const std::shared_ptr<job_t> &job, const process
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle status update for child \c pid.
|
/// Set the status of \p proc to \p status.
|
||||||
///
|
static void handle_child_status(process_t *proc, proc_status_t status) {
|
||||||
/// \param pid the pid of the process whose status changes
|
proc->status = status;
|
||||||
/// \param status the status as returned by wait
|
if (status.stopped()) {
|
||||||
static void handle_child_status(pid_t pid, proc_status_t status) {
|
proc->stopped = true;
|
||||||
job_t *j = NULL;
|
|
||||||
const process_t *found_proc = NULL;
|
|
||||||
|
|
||||||
job_iterator_t jobs;
|
|
||||||
while (!found_proc && (j = jobs.next())) {
|
|
||||||
process_t *prev = NULL;
|
|
||||||
for (process_ptr_t &p : j->processes) {
|
|
||||||
if (pid == p->pid) {
|
|
||||||
mark_process_status(p.get(), status);
|
|
||||||
found_proc = p.get();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
prev = p.get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the child process was not killed by a signal or other than SIGINT or SIGQUIT we're done.
|
|
||||||
if (!status.signal_exited() ||
|
|
||||||
(status.signal_code() != SIGINT && status.signal_code() != SIGQUIT)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_interactive_session) {
|
|
||||||
// In an interactive session, tell the principal parser to skip all blocks we're executing
|
|
||||||
// so control-C returns control to the user.
|
|
||||||
if (found_proc) parser_t::skip_all_blocks();
|
|
||||||
} else {
|
} else {
|
||||||
// Deliver the SIGINT or SIGQUIT signal to ourself since we're not interactive.
|
proc->completed = true;
|
||||||
struct sigaction act;
|
}
|
||||||
sigemptyset(&act.sa_mask);
|
|
||||||
act.sa_flags = 0;
|
// If the child was killed by SIGINT or SIGQUIT, then treat it as if we received that signal.
|
||||||
act.sa_handler = SIG_DFL;
|
if (status.signal_exited()) {
|
||||||
sigaction(SIGINT, &act, 0);
|
int sig = status.signal_code();
|
||||||
sigaction(SIGQUIT, &act, 0);
|
if (sig == SIGINT || sig == SIGQUIT) {
|
||||||
kill(getpid(), status.signal_code());
|
if (is_interactive_session) {
|
||||||
|
// In an interactive session, tell the principal parser to skip all blocks we're
|
||||||
|
// executing so control-C returns control to the user.
|
||||||
|
parser_t::skip_all_blocks();
|
||||||
|
} else {
|
||||||
|
// Deliver the SIGINT or SIGQUIT signal to ourself since we're not interactive.
|
||||||
|
struct sigaction act;
|
||||||
|
sigemptyset(&act.sa_mask);
|
||||||
|
act.sa_flags = 0;
|
||||||
|
act.sa_handler = SIG_DFL;
|
||||||
|
sigaction(sig, &act, 0);
|
||||||
|
kill(getpid(), sig);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,7 +414,7 @@ static void process_mark_finished_children(bool block_ok) {
|
||||||
if (pid > 0) {
|
if (pid > 0) {
|
||||||
assert(pid == proc->pid && "Unexpcted waitpid() return");
|
assert(pid == proc->pid && "Unexpcted waitpid() return");
|
||||||
debug(4, "Reaped PID %d", pid);
|
debug(4, "Reaped PID %d", pid);
|
||||||
handle_child_status(pid, proc_status_t::from_waitpid(status));
|
handle_child_status(proc.get(), proc_status_t::from_waitpid(status));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(0 && "Don't know how to reap this process");
|
assert(0 && "Don't know how to reap this process");
|
||||||
|
|
|
@ -223,9 +223,9 @@ class process_t {
|
||||||
/// File descriptor that pipe output should bind to.
|
/// File descriptor that pipe output should bind to.
|
||||||
int pipe_write_fd{0};
|
int pipe_write_fd{0};
|
||||||
/// True if process has completed.
|
/// True if process has completed.
|
||||||
volatile bool completed{false};
|
bool completed{false};
|
||||||
/// True if process has stopped.
|
/// True if process has stopped.
|
||||||
volatile bool stopped{false};
|
bool stopped{false};
|
||||||
/// Reported status value.
|
/// Reported status value.
|
||||||
proc_status_t status{};
|
proc_status_t status{};
|
||||||
#ifdef HAVE__PROC_SELF_STAT
|
#ifdef HAVE__PROC_SELF_STAT
|
||||||
|
|
Loading…
Reference in a new issue