Fixed logic for EINTR propagation
This commit is contained in:
@@ -29,29 +29,38 @@ pub fn signals_pending() -> bool {
|
||||
|
||||
pub fn check_signals() -> ShResult<()> {
|
||||
if GOT_SIGINT.swap(false, Ordering::SeqCst) {
|
||||
flog!(DEBUG, "check_signals: processing SIGINT");
|
||||
interrupt()?;
|
||||
return Err(ShErr::simple(ShErrKind::ClearReadline, ""));
|
||||
}
|
||||
if GOT_SIGHUP.swap(false, Ordering::SeqCst) {
|
||||
flog!(DEBUG, "check_signals: processing SIGHUP");
|
||||
hang_up(0);
|
||||
}
|
||||
if GOT_SIGTSTP.swap(false, Ordering::SeqCst) {
|
||||
flog!(DEBUG, "check_signals: processing SIGTSTP");
|
||||
terminal_stop()?;
|
||||
}
|
||||
if REAPING_ENABLED.load(Ordering::SeqCst) && GOT_SIGCHLD.swap(false, Ordering::SeqCst) {
|
||||
flog!(DEBUG, "check_signals: processing SIGCHLD (reaping enabled)");
|
||||
wait_child()?;
|
||||
} else if GOT_SIGCHLD.load(Ordering::SeqCst) {
|
||||
flog!(DEBUG, "check_signals: SIGCHLD pending but reaping disabled");
|
||||
}
|
||||
if SHOULD_QUIT.load(Ordering::SeqCst) {
|
||||
let code = QUIT_CODE.load(Ordering::SeqCst);
|
||||
flog!(DEBUG, "check_signals: SHOULD_QUIT set, exiting with code {}", code);
|
||||
return Err(ShErr::simple(ShErrKind::CleanExit(code), "exit"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn disable_reaping() {
|
||||
flog!(DEBUG, "disable_reaping: turning off SIGCHLD processing");
|
||||
REAPING_ENABLED.store(false, Ordering::SeqCst);
|
||||
}
|
||||
pub fn enable_reaping() {
|
||||
flog!(DEBUG, "enable_reaping: turning on SIGCHLD processing");
|
||||
REAPING_ENABLED.store(true, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
@@ -142,12 +151,15 @@ extern "C" fn handle_sigint(_: libc::c_int) {
|
||||
}
|
||||
|
||||
pub fn interrupt() -> ShResult<()> {
|
||||
flog!(DEBUG, "interrupt: checking for fg job to send SIGINT");
|
||||
write_jobs(|j| {
|
||||
if let Some(job) = j.get_fg_mut() {
|
||||
flog!(DEBUG, "interrupt: sending SIGINT to fg job pgid {}", job.pgid());
|
||||
job.killpg(Signal::SIGINT)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
flog!(DEBUG, "interrupt: no fg job, clearing readline");
|
||||
Ok(())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -161,18 +173,34 @@ extern "C" fn handle_sigchld(_: libc::c_int) {
|
||||
}
|
||||
|
||||
pub fn wait_child() -> ShResult<()> {
|
||||
flog!(DEBUG, "wait_child: starting reap loop");
|
||||
let flags = WtFlag::WNOHANG | WtFlag::WSTOPPED;
|
||||
while let Ok(status) = waitpid(None, Some(flags)) {
|
||||
match status {
|
||||
WtStat::Exited(pid, _) => child_exited(pid, status)?,
|
||||
WtStat::Signaled(pid, signal, _) => child_signaled(pid, signal)?,
|
||||
WtStat::Stopped(pid, signal) => child_stopped(pid, signal)?,
|
||||
WtStat::Continued(pid) => child_continued(pid)?,
|
||||
WtStat::StillAlive => break,
|
||||
WtStat::Exited(pid, code) => {
|
||||
flog!(DEBUG, "wait_child: pid {} exited with code {}", pid, code);
|
||||
child_exited(pid, status)?;
|
||||
}
|
||||
WtStat::Signaled(pid, signal, _) => {
|
||||
flog!(DEBUG, "wait_child: pid {} signaled with {:?}", pid, signal);
|
||||
child_signaled(pid, signal)?;
|
||||
}
|
||||
WtStat::Stopped(pid, signal) => {
|
||||
flog!(DEBUG, "wait_child: pid {} stopped with {:?}", pid, signal);
|
||||
child_stopped(pid, signal)?;
|
||||
}
|
||||
WtStat::Continued(pid) => {
|
||||
flog!(DEBUG, "wait_child: pid {} continued", pid);
|
||||
child_continued(pid)?;
|
||||
}
|
||||
WtStat::StillAlive => {
|
||||
flog!(DEBUG, "wait_child: no more children to reap");
|
||||
break;
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn child_signaled(pid: Pid, sig: Signal) -> ShResult<()> {
|
||||
|
||||
Reference in New Issue
Block a user