mirror of
https://github.com/wez/wezterm.git
synced 2024-12-22 21:01:36 +03:00
pty: ExitStatus now understands signals and impl Display
Improves the fidelity of the information in ExitStatus and shows it in the wezterm exit_behavior output to clarify the status.
This commit is contained in:
parent
317bfeef41
commit
0f6ee20b28
@ -164,8 +164,9 @@ impl Pane for LocalPane {
|
||||
(ExitBehavior::Close, _, _) => *proc = ProcessState::Dead,
|
||||
(ExitBehavior::CloseOnCleanExit, false, false) => {
|
||||
notify = Some(format!(
|
||||
"\r\n⚠️ Process {} didn't exit cleanly.\r\n{}=\"CloseOnCleanExit\"\r\n",
|
||||
"\r\n⚠️ Process {} didn't exit cleanly\r\n{}.\r\n{}=\"CloseOnCleanExit\"\r\n",
|
||||
self.command_description,
|
||||
status,
|
||||
EXIT_BEHAVIOR
|
||||
));
|
||||
*proc = ProcessState::DeadPendingClose { killed: false }
|
||||
@ -179,8 +180,10 @@ impl Pane for LocalPane {
|
||||
));
|
||||
} else {
|
||||
notify = Some(format!(
|
||||
"\r\n⚠️ Process {} didn't exit cleanly.\r\n{}=\"Hold\"\r\n",
|
||||
self.command_description, EXIT_BEHAVIOR
|
||||
"\r\n⚠️ Process {} didn't exit cleanly\r\n{}.\r\n{}=\"Hold\"\r\n",
|
||||
self.command_description,
|
||||
status,
|
||||
EXIT_BEHAVIOR
|
||||
));
|
||||
}
|
||||
*proc = ProcessState::DeadPendingClose { killed: false }
|
||||
|
@ -154,30 +154,76 @@ pub trait SlavePty {
|
||||
}
|
||||
|
||||
/// Represents the exit status of a child process.
|
||||
/// This is rather anemic in the current version of this crate,
|
||||
/// holding only an indicator of success or failure.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ExitStatus {
|
||||
successful: bool,
|
||||
code: u32,
|
||||
signal: Option<String>,
|
||||
}
|
||||
|
||||
impl ExitStatus {
|
||||
/// Construct an ExitStatus from a process return code
|
||||
pub fn with_exit_code(code: u32) -> Self {
|
||||
Self { code, signal: None }
|
||||
}
|
||||
|
||||
/// Construct an ExitStatus from a signal name
|
||||
pub fn with_signal(signal: &str) -> Self {
|
||||
Self {
|
||||
successful: code == 0,
|
||||
code: 1,
|
||||
signal: Some(signal.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the status indicates successful completion
|
||||
pub fn success(&self) -> bool {
|
||||
self.successful
|
||||
match self.signal {
|
||||
None => self.code == 0,
|
||||
Some(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::process::ExitStatus> for ExitStatus {
|
||||
fn from(status: std::process::ExitStatus) -> ExitStatus {
|
||||
ExitStatus {
|
||||
successful: status.success(),
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::process::ExitStatusExt;
|
||||
|
||||
if let Some(signal) = status.signal() {
|
||||
let signame = unsafe { libc::strsignal(signal) };
|
||||
let signal = if signame.is_null() {
|
||||
format!("Signal {}", signal)
|
||||
} else {
|
||||
let signame = unsafe { std::ffi::CStr::from_ptr(signame) };
|
||||
signame.to_string_lossy().to_string()
|
||||
};
|
||||
|
||||
return ExitStatus {
|
||||
code: status.code().map(|c| c as u32).unwrap_or(1),
|
||||
signal: Some(signal),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let code =
|
||||
status
|
||||
.code()
|
||||
.map(|c| c as u32)
|
||||
.unwrap_or_else(|| if status.success() { 0 } else { 1 });
|
||||
|
||||
ExitStatus { code, signal: None }
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ExitStatus {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
if self.success() {
|
||||
write!(fmt, "Success")
|
||||
} else {
|
||||
match &self.signal {
|
||||
Some(sig) => write!(fmt, "Terminated by {}", sig),
|
||||
None => write!(fmt, "Exited with code {}", self.code),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,10 @@ impl ChannelWrap {
|
||||
#[cfg(feature = "ssh2")]
|
||||
Self::Ssh2(chan) => {
|
||||
if chan.eof() && chan.wait_close().is_ok() {
|
||||
if let Some(_sig) = has_signal(chan) {
|
||||
Some(ExitStatus::with_exit_code(1))
|
||||
if let Some(sig) = has_signal(chan) {
|
||||
Some(ExitStatus::with_signal(
|
||||
sig.exit_signal.as_deref().unwrap_or("Unknown signal"),
|
||||
))
|
||||
} else if let Ok(status) = chan.exit_status() {
|
||||
Some(ExitStatus::with_exit_code(status as _))
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user