Drop child read handle as soon as possible

This commit is contained in:
Austen Adler 2022-12-18 11:16:43 -05:00
parent 82239eeb8e
commit 853770613e
3 changed files with 30 additions and 20 deletions

View File

@ -15,11 +15,13 @@ use std::{
pub type CommandRequest = (Arc<RwLock<CommandOptions>>, Arc<String>); pub type CommandRequest = (Arc<RwLock<CommandOptions>>, Arc<String>);
use crate::App; use crate::App;
#[derive(Debug)]
pub enum CommandCompleted { pub enum CommandCompleted {
Success(CommandResult), Success(CommandResult),
Failure(Vec<u8>), Failure(Vec<u8>),
} }
#[derive(Debug)]
pub struct CommandResult { pub struct CommandResult {
pub status_success: bool, pub status_success: bool,
pub stdout: Vec<u8>, pub stdout: Vec<u8>,
@ -84,29 +86,35 @@ pub fn command_event_loop(
// } // }
fn run_inner(command_request: CommandRequest) -> Result<CommandResult> { fn run_inner(command_request: CommandRequest) -> Result<CommandResult> {
let request = command_request.0.read(); // Spawn the child
let mut child = {
let request = command_request.0.read();
let mut command = Command::new(&request.command); let mut command = Command::new(&request.command);
command command
.stdin(Stdio::piped()) .stdin(Stdio::piped())
.stdout(Stdio::piped()) .stdout(Stdio::piped())
.stderr(Stdio::piped()) .stderr(Stdio::piped())
.args(&request.hidden_options); .args(&request.hidden_options);
if request.wordsplit { if request.wordsplit {
match shellwords::split(&request.cmdline) { match shellwords::split(&request.cmdline) {
Ok(a) => { Ok(a) => {
command.args(a); command.args(a);
} }
Err(e) => { Err(e) => {
bail!("Argument error: {e:?}"); bail!("Argument error: {e:?}");
}
} }
} else {
// TODO: Avoid cloning here
command.arg(&request.cmdline);
} }
} else {
// TODO: Avoid cloning here std::mem::drop(request);
command.arg(&request.cmdline);
} command.spawn()
let mut child = command.spawn()?; }?;
let mut stdin = child.stdin.take().context("Could not take stdin")?; let mut stdin = child.stdin.take().context("Could not take stdin")?;
let text_orig_clone = command_request.1.clone(); let text_orig_clone = command_request.1.clone();

View File

@ -3,6 +3,7 @@ use anyhow::bail;
use anyhow::Result; use anyhow::Result;
use crossbeam::channel::Sender; use crossbeam::channel::Sender;
#[derive(Debug)]
pub enum EventMessage { pub enum EventMessage {
CommandCompleted(CommandCompleted), CommandCompleted(CommandCompleted),
CrosstermEvent(crossterm::event::Event), CrosstermEvent(crossterm::event::Event),

View File

@ -273,18 +273,19 @@ fn init_message_passing() -> (Receiver<EventMessage>, Sender<CommandRequest>) {
let _result = command::command_event_loop(command_request_rx, command_message_tx); let _result = command::command_event_loop(command_request_rx, command_message_tx);
}); });
// Drop the remaining transmitter
std::mem::drop(message_tx); std::mem::drop(message_tx);
(message_rx, command_request_tx) (message_rx, command_request_tx)
} }
fn run_app<B: Backend>(terminal: &mut Terminal<B>, app: App) -> Result<Option<(String, Vec<u8>)>> { fn run_app<B: Backend>(terminal: &mut Terminal<B>, app: App) -> Result<Option<(String, Vec<u8>)>> {
// When starting the app, ensure the command runs at least once
{ {
let mut command_options = app.command_options.write(); let mut command_options = app.command_options.write();
if !command_options.cmdline.is_empty() { if !command_options.cmdline.is_empty() {
app.run_command()?; app.run_command()?;
// command_request_tx.send((app.command_options.clone(), app.text_orig.clone()))?;
} }
if command_options.cmdline_position == 0 { if command_options.cmdline_position == 0 {