Skip to content

Commit

Permalink
correctly exit when child exit
Browse files Browse the repository at this point in the history
  • Loading branch information
blahgeek committed Jan 2, 2024
1 parent 36f2ff4 commit 9c43320
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 35 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ serde_json = "1.0"
anyhow = "1.0"
lazy_static = "1.4"
smallvec = "1.11"
tempfile = "3.9"
env_logger = "0.10"
log = "0.4.20"

Expand All @@ -21,3 +20,4 @@ crate-type = ["cdylib"]

[dev-dependencies]
emacs = "0.18"
tempfile = "3.9"
62 changes: 30 additions & 32 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ fn process_server_reader(reader: impl std::io::Read,

pub fn run_app_forever(client_reader: impl std::io::Read + Send + 'static,
client_writer: impl std::io::Write + Send + 'static,
mut server_cmd: std::process::Command) -> Result<()> {
mut server_cmd: std::process::Command) -> Result<std::process::ExitStatus> {
info!("Running server {:?}", server_cmd);
let proc = server_cmd
let mut proc = server_cmd
.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::inherit())
Expand All @@ -98,37 +98,35 @@ pub fn run_app_forever(client_reader: impl std::io::Read + Send + 'static,
let c2s_channel_counter = Arc::new(AtomicI32::new(0));
let (s2c_channel_pub, s2c_channel_sub) = mpsc::channel::<String>();

let threads = vec![
{
let c2s_channel_counter = c2s_channel_counter.clone();
std::thread::spawn(move || {
info!("Started client->server write thread");
process_channel_to_writer(c2s_channel_sub, Some(c2s_channel_counter), proc.stdin.unwrap()).unwrap();
info!("Finished client->server write thread");
})
},
{
let c2s_channel_counter = c2s_channel_counter.clone();
let proc_stdin = proc.stdin.take().unwrap();
std::thread::spawn(move || {
info!("Started server->client write thread");
process_channel_to_writer(s2c_channel_sub, None, client_writer).unwrap();
info!("Finished server->client write thread");
}),
{
let s2c_channel_pub = s2c_channel_pub.clone();
std::thread::spawn(move || {
info!("Started server->client read thread");
process_server_reader(proc.stdout.unwrap(), s2c_channel_pub).unwrap();
info!("Finished server->client read thread");
})
},
info!("Started client->server write thread");
process_channel_to_writer(c2s_channel_sub, Some(c2s_channel_counter), proc_stdin).unwrap();
info!("Finished client->server write thread");
});
}
std::thread::spawn(move || {
info!("Started server->client write thread");
process_channel_to_writer(s2c_channel_sub, None, client_writer).unwrap();
info!("Finished server->client write thread");
});
{
let s2c_channel_pub = s2c_channel_pub.clone();
let proc_stdout = proc.stdout.take().unwrap();
std::thread::spawn(move || {
info!("Started client->server read thread");
process_client_reader(
client_reader, c2s_channel_pub, c2s_channel_counter, s2c_channel_pub).unwrap();
info!("Finished client->server read thread");
}),
];

threads.into_iter().for_each(|x| x.join().unwrap());
info!("Started server->client read thread");
process_server_reader(proc_stdout, s2c_channel_pub).unwrap();
info!("Finished server->client read thread");
});
}
std::thread::spawn(move || {
info!("Started client->server read thread");
process_client_reader(
client_reader, c2s_channel_pub, c2s_channel_counter, s2c_channel_pub).unwrap();
info!("Finished client->server read thread");
});

Ok(())
Ok(proc.wait()?)
}
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub mod bytecode;
mod rpcio;
pub mod rpcio;
mod lsp_message;
pub mod app;
3 changes: 2 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ fn main() -> Result<()> {
let mut cmd = std::process::Command::new(&args[1]);
cmd.args(&args[2..]);

app::run_app_forever(std::io::stdin(), std::io::stdout(), cmd)
let exit_status = app::run_app_forever(std::io::stdin(), std::io::stdout(), cmd)?;
std::process::exit(exit_status.code().unwrap_or(1))
}
35 changes: 35 additions & 0 deletions tests/app_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use anyhow::Result;
use tempfile;
use env_logger;

use emacs_lsp_booster::{app, rpcio};

#[test]
fn test_app_with_echo_server() -> Result<()> {
env_logger::init();

let (input_pair_in, input_pair_out) = std::os::unix::net::UnixStream::pair()?;
let tmpdir = tempfile::tempdir()?;
let output_file = std::fs::File::create(tmpdir.path().join("output.txt"))?;

std::thread::spawn(move || {
let mut input_bufwriter = std::io::BufWriter::new(input_pair_in);
for _ in 0..10 {
rpcio::rpc_write(&mut input_bufwriter, "{}").unwrap();
}
loop {
std::thread::park();
}
});

let mut cmd = std::process::Command::new("timeout");
cmd.args(&["1", "cat"]);

let exit_status = app::run_app_forever(input_pair_out, output_file, cmd)?;
assert!(!exit_status.success()); // timeout kill

let output = std::fs::read_to_string(tmpdir.path().join("output.txt"))?;
assert_eq!(output.chars().filter(|x| *x == '#').count(), 10);

Ok(())
}

0 comments on commit 9c43320

Please sign in to comment.