Save forked processes for reaping
parent
6c76db2063
commit
9d20fd5576
|
@ -912,21 +912,26 @@ impl Component for Composer {
|
|||
|
||||
let parts = split_command!(editor);
|
||||
let (cmd, args) = (parts[0], &parts[1..]);
|
||||
if let Err(e) = Command::new(cmd)
|
||||
match Command::new(cmd)
|
||||
.args(args)
|
||||
.arg(&f.path())
|
||||
.stdin(Stdio::inherit())
|
||||
.stdout(Stdio::inherit())
|
||||
.output()
|
||||
.spawn()
|
||||
{
|
||||
context.replies.push_back(UIEvent::Notification(
|
||||
Some(format!("Failed to execute {}", editor)),
|
||||
e.to_string(),
|
||||
Some(NotificationType::ERROR),
|
||||
));
|
||||
context.replies.push_back(UIEvent::Fork(ForkType::Finished));
|
||||
context.restore_input();
|
||||
return true;
|
||||
Ok(mut child) => {
|
||||
let _ = child.wait();
|
||||
}
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::Notification(
|
||||
Some(format!("Failed to execute {}: {}", editor, err)),
|
||||
err.to_string(),
|
||||
Some(NotificationType::ERROR),
|
||||
));
|
||||
context.replies.push_back(UIEvent::Fork(ForkType::Finished));
|
||||
context.restore_input();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
context.replies.push_back(UIEvent::Fork(ForkType::Finished));
|
||||
let result = f.read_to_string();
|
||||
|
@ -973,7 +978,7 @@ impl Component for Composer {
|
|||
.spawn()
|
||||
{
|
||||
Ok(child) => {
|
||||
let out = child
|
||||
let _ = child
|
||||
.wait_with_output()
|
||||
.expect("failed to launch cmd")
|
||||
.stdout;
|
||||
|
@ -1005,7 +1010,7 @@ impl Component for Composer {
|
|||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::Notification(
|
||||
None,
|
||||
format!("could not execute pipe cmd: {}", cmd),
|
||||
format!("could not execute pipe cmd {}: {}", cmd, err),
|
||||
Some(NotificationType::ERROR),
|
||||
));
|
||||
return true;
|
||||
|
|
|
@ -1117,15 +1117,26 @@ impl Component for MailView {
|
|||
}
|
||||
_ => {}
|
||||
}
|
||||
Command::new(&binary)
|
||||
match Command::new(&binary)
|
||||
.arg(p.path())
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap_or_else(|_| {
|
||||
panic!("Failed to start {}", binary.display())
|
||||
});
|
||||
context.temp_files.push(p);
|
||||
{
|
||||
Ok(child) => {
|
||||
context.temp_files.push(p);
|
||||
context.children.push(child);
|
||||
}
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(format!(
|
||||
"Failed to start {}: {}",
|
||||
binary.display(),
|
||||
err
|
||||
)),
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(if name.is_some() {
|
||||
|
@ -1217,17 +1228,22 @@ impl Component for MailView {
|
|||
}
|
||||
};
|
||||
|
||||
if let Err(e) = Command::new("xdg-open")
|
||||
match Command::new("xdg-open")
|
||||
.arg(url)
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
{
|
||||
context.replies.push_back(UIEvent::Notification(
|
||||
Some("Failed to launch xdg-open".to_string()),
|
||||
e.to_string(),
|
||||
Some(NotificationType::ERROR),
|
||||
));
|
||||
Ok(child) => {
|
||||
context.children.push(child);
|
||||
}
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::Notification(
|
||||
Some("Failed to launch xdg-open".to_string()),
|
||||
err.to_string(),
|
||||
Some(NotificationType::ERROR),
|
||||
));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1427,18 +1443,23 @@ impl Component for MailView {
|
|||
}
|
||||
}
|
||||
list_management::ListAction::Url(url) => {
|
||||
if let Err(e) = Command::new("xdg-open")
|
||||
match Command::new("xdg-open")
|
||||
.arg(String::from_utf8_lossy(url).into_owned())
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
{
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(format!(
|
||||
"Couldn't launch xdg-open: {}",
|
||||
e
|
||||
)),
|
||||
));
|
||||
Ok(child) => {
|
||||
context.children.push(child);
|
||||
}
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(format!(
|
||||
"Couldn't launch xdg-open: {}",
|
||||
err
|
||||
)),
|
||||
));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1447,18 +1468,21 @@ impl Component for MailView {
|
|||
}
|
||||
MailingListAction::ListArchive if actions.archive.is_some() => {
|
||||
/* open archive url with xdg-open */
|
||||
if let Err(e) = Command::new("xdg-open")
|
||||
match Command::new("xdg-open")
|
||||
.arg(actions.archive.unwrap())
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
{
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(format!(
|
||||
"Couldn't launch xdg-open: {}",
|
||||
e
|
||||
)),
|
||||
));
|
||||
Ok(child) => context.children.push(child),
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(format!(
|
||||
"Couldn't launch xdg-open: {}",
|
||||
err
|
||||
)),
|
||||
));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -454,15 +454,26 @@ impl Component for EnvelopeView {
|
|||
None,
|
||||
true,
|
||||
);
|
||||
Command::new(&binary)
|
||||
match Command::new(&binary)
|
||||
.arg(p.path())
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap_or_else(|_| {
|
||||
panic!("Failed to start {}", binary.display())
|
||||
});
|
||||
context.temp_files.push(p);
|
||||
{
|
||||
Ok(child) => {
|
||||
context.children.push(child);
|
||||
context.temp_files.push(p);
|
||||
}
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(format!(
|
||||
"Failed to start {}: {}",
|
||||
binary.display(),
|
||||
err
|
||||
)),
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(format!(
|
||||
|
@ -528,12 +539,17 @@ impl Component for EnvelopeView {
|
|||
}
|
||||
};
|
||||
|
||||
Command::new("xdg-open")
|
||||
match Command::new("xdg-open")
|
||||
.arg(url)
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
.expect("Failed to start xdg_open");
|
||||
{
|
||||
Ok(child) => context.children.push(child),
|
||||
Err(_err) => context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage("Failed to start xdg_open".into()),
|
||||
)),
|
||||
}
|
||||
return true;
|
||||
}
|
||||
UIEvent::Input(Key::Char('u')) => {
|
||||
|
|
|
@ -137,13 +137,26 @@ impl Component for HtmlView {
|
|||
let binary = query_default_app("text/html");
|
||||
if let Ok(binary) = binary {
|
||||
let p = create_temp_file(&self.bytes, None, None, true);
|
||||
Command::new(&binary)
|
||||
match Command::new(&binary)
|
||||
.arg(p.path())
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap_or_else(|_| panic!("Failed to start {}", binary.display()));
|
||||
context.temp_files.push(p);
|
||||
{
|
||||
Ok(child) => {
|
||||
context.temp_files.push(p);
|
||||
context.children.push(child);
|
||||
}
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(format!(
|
||||
"Failed to start {}: {}",
|
||||
binary.display(),
|
||||
err
|
||||
)),
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
context
|
||||
.replies
|
||||
|
|
|
@ -165,18 +165,23 @@ impl Component for NotificationFilter {
|
|||
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
|
||||
if let UIEvent::Notification(ref title, ref body, ref kind) = event {
|
||||
if let Some(ref bin) = context.runtime_settings.notifications.script {
|
||||
if let Err(err) = Command::new(bin)
|
||||
match Command::new(bin)
|
||||
.arg(title.as_ref().map(String::as_str).unwrap_or("meli"))
|
||||
.arg(body)
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
{
|
||||
log(
|
||||
format!("Could not run notification script: {}.", err.to_string()),
|
||||
ERROR,
|
||||
);
|
||||
debug!("{:?}", err);
|
||||
Ok(child) => {
|
||||
context.children.push(child);
|
||||
}
|
||||
Err(err) => {
|
||||
log(
|
||||
format!("Could not run notification script: {}.", err.to_string()),
|
||||
ERROR,
|
||||
);
|
||||
debug!("{:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -627,7 +627,7 @@ impl Account {
|
|||
if let Some(ref refresh_command) = self.settings.conf().refresh_command {
|
||||
let parts = crate::split_command!(refresh_command);
|
||||
let (cmd, args) = (parts[0], &parts[1..]);
|
||||
std::process::Command::new(cmd)
|
||||
let child = std::process::Command::new(cmd)
|
||||
.args(args)
|
||||
.stdin(std::process::Stdio::null())
|
||||
.stdout(std::process::Stdio::null())
|
||||
|
@ -638,6 +638,11 @@ impl Account {
|
|||
StatusEvent::DisplayMessage(format!("Running command {}", refresh_command)),
|
||||
)))
|
||||
.unwrap();
|
||||
self.sender
|
||||
.send(ThreadEvent::UIEvent(UIEvent::Fork(
|
||||
crate::ForkType::Generic(child),
|
||||
)))
|
||||
.unwrap();
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
|
16
src/state.rs
16
src/state.rs
|
@ -103,6 +103,7 @@ pub struct Context {
|
|||
receiver: Receiver<ThreadEvent>,
|
||||
input: InputHandler,
|
||||
work_controller: WorkController,
|
||||
pub children: Vec<std::process::Child>,
|
||||
pub plugin_manager: PluginManager,
|
||||
|
||||
pub temp_files: Vec<File>,
|
||||
|
@ -216,8 +217,16 @@ impl Drop for State {
|
|||
fn drop(&mut self) {
|
||||
// When done, restore the defaults to avoid messing with the terminal.
|
||||
self.switch_to_main_screen();
|
||||
use nix::sys::wait::{waitpid, WaitPidFlag};
|
||||
for child in self.context.children.iter_mut() {
|
||||
if let Err(err) = waitpid(
|
||||
nix::unistd::Pid::from_raw(child.id() as i32),
|
||||
Some(WaitPidFlag::WNOHANG),
|
||||
) {
|
||||
debug!("Failed to wait on subprocess {}: {}", child.id(), err);
|
||||
}
|
||||
}
|
||||
if let Some(ForkType::Embed(child_pid)) = self.child.take() {
|
||||
use nix::sys::wait::{waitpid, WaitPidFlag};
|
||||
/* Try wait, we don't want to block */
|
||||
if let Err(e) = waitpid(child_pid, Some(WaitPidFlag::WNOHANG)) {
|
||||
debug!("Failed to wait on subprocess {}: {}", child_pid, e);
|
||||
|
@ -329,6 +338,7 @@ impl State {
|
|||
replies: VecDeque::with_capacity(5),
|
||||
temp_files: Vec::new(),
|
||||
work_controller,
|
||||
children: vec![],
|
||||
plugin_manager,
|
||||
|
||||
sender,
|
||||
|
@ -911,6 +921,10 @@ impl State {
|
|||
self.context.restore_input();
|
||||
return;
|
||||
}
|
||||
UIEvent::Fork(ForkType::Generic(child)) => {
|
||||
self.context.children.push(child);
|
||||
return;
|
||||
}
|
||||
UIEvent::Fork(child) => {
|
||||
self.mode = UIMode::Fork;
|
||||
self.child = Some(child);
|
||||
|
|
Loading…
Reference in New Issue