aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-01-29 12:51:52 +0000
committerGitHub <[email protected]>2020-01-29 12:51:52 +0000
commitabc5828c057f65c8caa7e1adaca4d55519be457b (patch)
treefa72ecad87a91d9613591a464af6a57f723eb65d
parent9f68f7acf2e4cae65122cae072bae2386f48bff1 (diff)
parent4ec5f6e25850b3064b258739eabefdeb8a4bd1b5 (diff)
Merge #2937
2937: Parse cargo output a line at a time. r=kiljacken a=kiljacken We previously used serde's stream deserializer to read json blobs from the cargo output. It has an issue though: If the deserializer encounters invalid input, it gets stuck reporting the same error again and again because it is unable to foward over the input until it reaches a new valid object. Reading a line at a time and manually deserializing fixes this issue, because cargo makes sure to only outpu one json blob per line, so should we encounter invalid input, we can just skip a line and continue. The main reason this would happen is stray printf-debugging in procedural macros, so we still report that an error occured, but we handle it gracefully now. Fixes #2935 Co-authored-by: Emil Lauridsen <[email protected]>
-rw-r--r--crates/ra_cargo_watch/Cargo.toml1
-rw-r--r--crates/ra_cargo_watch/src/lib.rs30
2 files changed, 26 insertions, 5 deletions
diff --git a/crates/ra_cargo_watch/Cargo.toml b/crates/ra_cargo_watch/Cargo.toml
index 49e06e0d3..dd814fc9d 100644
--- a/crates/ra_cargo_watch/Cargo.toml
+++ b/crates/ra_cargo_watch/Cargo.toml
@@ -11,6 +11,7 @@ log = "0.4.3"
11cargo_metadata = "0.9.1" 11cargo_metadata = "0.9.1"
12jod-thread = "0.1.0" 12jod-thread = "0.1.0"
13parking_lot = "0.10.0" 13parking_lot = "0.10.0"
14serde_json = "1.0.45"
14 15
15[dev-dependencies] 16[dev-dependencies]
16insta = "0.13.0" 17insta = "0.13.0"
diff --git a/crates/ra_cargo_watch/src/lib.rs b/crates/ra_cargo_watch/src/lib.rs
index 9af9c347d..ea7ddc86b 100644
--- a/crates/ra_cargo_watch/src/lib.rs
+++ b/crates/ra_cargo_watch/src/lib.rs
@@ -9,7 +9,7 @@ use lsp_types::{
9}; 9};
10use std::{ 10use std::{
11 collections::HashMap, 11 collections::HashMap,
12 io::BufReader, 12 io::{BufRead, BufReader},
13 path::PathBuf, 13 path::PathBuf,
14 process::{Command, Stdio}, 14 process::{Command, Stdio},
15 sync::Arc, 15 sync::Arc,
@@ -350,13 +350,33 @@ impl WatchThread {
350 // which will break out of the loop, and continue the shutdown 350 // which will break out of the loop, and continue the shutdown
351 let _ = message_send.send(CheckEvent::Begin); 351 let _ = message_send.send(CheckEvent::Begin);
352 352
353 for message in 353 // We manually read a line at a time, instead of using serde's
354 cargo_metadata::parse_messages(BufReader::new(command.stdout.take().unwrap())) 354 // stream deserializers, because the deserializer cannot recover
355 { 355 // from an error, resulting in it getting stuck, because we try to
356 // be resillient against failures.
357 //
358 // Because cargo only outputs one JSON object per line, we can
359 // simply skip a line if it doesn't parse, which just ignores any
360 // erroneus output.
361 let stdout = BufReader::new(command.stdout.take().unwrap());
362 for line in stdout.lines() {
363 let line = match line {
364 Ok(line) => line,
365 Err(err) => {
366 log::error!("Couldn't read line from cargo: {}", err);
367 continue;
368 }
369 };
370
371 let message = serde_json::from_str::<cargo_metadata::Message>(&line);
356 let message = match message { 372 let message = match message {
357 Ok(message) => message, 373 Ok(message) => message,
358 Err(err) => { 374 Err(err) => {
359 log::error!("Invalid json from cargo check, ignoring: {}", err); 375 log::error!(
376 "Invalid json from cargo check, ignoring ({}): {:?} ",
377 err,
378 line
379 );
360 continue; 380 continue;
361 } 381 }
362 }; 382 };