Skip to content

Commit 9c43320

Browse files
committed
correctly exit when child exit
1 parent 36f2ff4 commit 9c43320

File tree

5 files changed

+69
-35
lines changed

5 files changed

+69
-35
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ serde_json = "1.0"
1111
anyhow = "1.0"
1212
lazy_static = "1.4"
1313
smallvec = "1.11"
14-
tempfile = "3.9"
1514
env_logger = "0.10"
1615
log = "0.4.20"
1716

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

2221
[dev-dependencies]
2322
emacs = "0.18"
23+
tempfile = "3.9"

src/app.rs

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,9 @@ fn process_server_reader(reader: impl std::io::Read,
8686

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

101-
let threads = vec![
102-
{
103-
let c2s_channel_counter = c2s_channel_counter.clone();
104-
std::thread::spawn(move || {
105-
info!("Started client->server write thread");
106-
process_channel_to_writer(c2s_channel_sub, Some(c2s_channel_counter), proc.stdin.unwrap()).unwrap();
107-
info!("Finished client->server write thread");
108-
})
109-
},
101+
{
102+
let c2s_channel_counter = c2s_channel_counter.clone();
103+
let proc_stdin = proc.stdin.take().unwrap();
110104
std::thread::spawn(move || {
111-
info!("Started server->client write thread");
112-
process_channel_to_writer(s2c_channel_sub, None, client_writer).unwrap();
113-
info!("Finished server->client write thread");
114-
}),
115-
{
116-
let s2c_channel_pub = s2c_channel_pub.clone();
117-
std::thread::spawn(move || {
118-
info!("Started server->client read thread");
119-
process_server_reader(proc.stdout.unwrap(), s2c_channel_pub).unwrap();
120-
info!("Finished server->client read thread");
121-
})
122-
},
105+
info!("Started client->server write thread");
106+
process_channel_to_writer(c2s_channel_sub, Some(c2s_channel_counter), proc_stdin).unwrap();
107+
info!("Finished client->server write thread");
108+
});
109+
}
110+
std::thread::spawn(move || {
111+
info!("Started server->client write thread");
112+
process_channel_to_writer(s2c_channel_sub, None, client_writer).unwrap();
113+
info!("Finished server->client write thread");
114+
});
115+
{
116+
let s2c_channel_pub = s2c_channel_pub.clone();
117+
let proc_stdout = proc.stdout.take().unwrap();
123118
std::thread::spawn(move || {
124-
info!("Started client->server read thread");
125-
process_client_reader(
126-
client_reader, c2s_channel_pub, c2s_channel_counter, s2c_channel_pub).unwrap();
127-
info!("Finished client->server read thread");
128-
}),
129-
];
130-
131-
threads.into_iter().for_each(|x| x.join().unwrap());
119+
info!("Started server->client read thread");
120+
process_server_reader(proc_stdout, s2c_channel_pub).unwrap();
121+
info!("Finished server->client read thread");
122+
});
123+
}
124+
std::thread::spawn(move || {
125+
info!("Started client->server read thread");
126+
process_client_reader(
127+
client_reader, c2s_channel_pub, c2s_channel_counter, s2c_channel_pub).unwrap();
128+
info!("Finished client->server read thread");
129+
});
132130

133-
Ok(())
131+
Ok(proc.wait()?)
134132
}

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
pub mod bytecode;
2-
mod rpcio;
2+
pub mod rpcio;
33
mod lsp_message;
44
pub mod app;

src/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ fn main() -> Result<()> {
2424
let mut cmd = std::process::Command::new(&args[1]);
2525
cmd.args(&args[2..]);
2626

27-
app::run_app_forever(std::io::stdin(), std::io::stdout(), cmd)
27+
let exit_status = app::run_app_forever(std::io::stdin(), std::io::stdout(), cmd)?;
28+
std::process::exit(exit_status.code().unwrap_or(1))
2829
}

tests/app_test.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use anyhow::Result;
2+
use tempfile;
3+
use env_logger;
4+
5+
use emacs_lsp_booster::{app, rpcio};
6+
7+
#[test]
8+
fn test_app_with_echo_server() -> Result<()> {
9+
env_logger::init();
10+
11+
let (input_pair_in, input_pair_out) = std::os::unix::net::UnixStream::pair()?;
12+
let tmpdir = tempfile::tempdir()?;
13+
let output_file = std::fs::File::create(tmpdir.path().join("output.txt"))?;
14+
15+
std::thread::spawn(move || {
16+
let mut input_bufwriter = std::io::BufWriter::new(input_pair_in);
17+
for _ in 0..10 {
18+
rpcio::rpc_write(&mut input_bufwriter, "{}").unwrap();
19+
}
20+
loop {
21+
std::thread::park();
22+
}
23+
});
24+
25+
let mut cmd = std::process::Command::new("timeout");
26+
cmd.args(&["1", "cat"]);
27+
28+
let exit_status = app::run_app_forever(input_pair_out, output_file, cmd)?;
29+
assert!(!exit_status.success()); // timeout kill
30+
31+
let output = std::fs::read_to_string(tmpdir.path().join("output.txt"))?;
32+
assert_eq!(output.chars().filter(|x| *x == '#').count(), 10);
33+
34+
Ok(())
35+
}

0 commit comments

Comments
 (0)