Skip to content

Commit cb7cff1

Browse files
committed
Auto merge of #8236 - ehuss:no-panic-output, r=alexcrichton
Ignore broken console output in some situations. If stdout or stderr is closed while Cargo is running, Cargo would panic in some situations (usually with EPIPE). For example, `cargo install --list | grep -q cargo-fuzz`, where `grep` will close stdout once it gets a match. This changes it so that Cargo will ignore output errors in most situations. Failure to output a regular build message still results in an error, which follows the behavior of some tools like `make`. All output, including stdout, now goes through `Shell`. Closes #5234
2 parents 55869de + 5a096da commit cb7cff1

29 files changed

+400
-149
lines changed

src/bin/cargo/cli.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use cargo::core::features;
2-
use cargo::{self, CliResult, Config};
2+
use cargo::{self, drop_print, drop_println, CliResult, Config};
33
use clap::{AppSettings, Arg, ArgMatches};
44

55
use super::commands;
@@ -25,7 +25,8 @@ pub fn main(config: &mut Config) -> CliResult {
2525
};
2626

2727
if args.value_of("unstable-features") == Some("help") {
28-
println!(
28+
drop_println!(
29+
config,
2930
"
3031
Available unstable (nightly-only) flags:
3132
@@ -40,15 +41,17 @@ Available unstable (nightly-only) flags:
4041
Run with 'cargo -Z [FLAG] [SUBCOMMAND]'"
4142
);
4243
if !features::nightly_features_allowed() {
43-
println!(
44+
drop_println!(
45+
config,
4446
"\nUnstable flags are only available on the nightly channel \
4547
of Cargo, but this is the `{}` channel.\n\
4648
{}",
4749
features::channel(),
4850
features::SEE_CHANNELS
4951
);
5052
}
51-
println!(
53+
drop_println!(
54+
config,
5255
"\nSee https://doc.rust-lang.org/nightly/cargo/reference/unstable.html \
5356
for more information about these flags."
5457
);
@@ -58,7 +61,7 @@ Run with 'cargo -Z [FLAG] [SUBCOMMAND]'"
5861
let is_verbose = args.occurrences_of("verbose") > 0;
5962
if args.is_present("version") {
6063
let version = get_version_string(is_verbose);
61-
print!("{}", version);
64+
drop_print!(config, "{}", version);
6265
return Ok(());
6366
}
6467

@@ -69,19 +72,19 @@ Run with 'cargo -Z [FLAG] [SUBCOMMAND]'"
6972
}
7073

7174
if args.is_present("list") {
72-
println!("Installed Commands:");
75+
drop_println!(config, "Installed Commands:");
7376
for command in list_commands(config) {
7477
match command {
7578
CommandInfo::BuiltIn { name, about } => {
7679
let summary = about.unwrap_or_default();
7780
let summary = summary.lines().next().unwrap_or(&summary); // display only the first line
78-
println!(" {:<20} {}", name, summary)
81+
drop_println!(config, " {:<20} {}", name, summary);
7982
}
8083
CommandInfo::External { name, path } => {
8184
if is_verbose {
82-
println!(" {:<20} {}", name, path.display())
85+
drop_println!(config, " {:<20} {}", name, path.display());
8386
} else {
84-
println!(" {}", name)
87+
drop_println!(config, " {}", name);
8588
}
8689
}
8790
}

src/bin/cargo/commands/locate_project.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
use crate::command_prelude::*;
2-
3-
use cargo::print_json;
42
use serde::Serialize;
53

64
pub fn cli() -> App {
@@ -30,6 +28,6 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
3028

3129
let location = ProjectLocation { root };
3230

33-
print_json(&location);
31+
config.shell().print_json(&location);
3432
Ok(())
3533
}

src/bin/cargo/commands/metadata.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
use crate::command_prelude::*;
2-
32
use cargo::ops::{self, OutputMetadataOptions};
4-
use cargo::print_json;
53

64
pub fn cli() -> App {
75
subcommand("metadata")
@@ -54,6 +52,6 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
5452
};
5553

5654
let result = ops::output_metadata(&ws, &options)?;
57-
print_json(&result);
55+
config.shell().print_json(&result);
5856
Ok(())
5957
}

src/bin/cargo/commands/pkgid.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,6 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
3737
let ws = args.workspace(config)?;
3838
let spec = args.value_of("spec").or_else(|| args.value_of("package"));
3939
let spec = ops::pkgid(&ws, spec)?;
40-
println!("{}", spec);
40+
cargo::drop_println!(config, "{}", spec);
4141
Ok(())
4242
}

src/bin/cargo/commands/read_manifest.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
use crate::command_prelude::*;
22

3-
use cargo::print_json;
4-
53
pub fn cli() -> App {
64
subcommand("read-manifest")
75
.about(
@@ -17,6 +15,6 @@ Deprecated, use `cargo metadata --no-deps` instead.\
1715

1816
pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
1917
let ws = args.workspace(config)?;
20-
print_json(&ws.current()?);
18+
config.shell().print_json(&ws.current()?);
2119
Ok(())
2220
}

src/bin/cargo/commands/tree.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
102102
if args.is_present("version") {
103103
let verbose = args.occurrences_of("verbose") > 0;
104104
let version = cli::get_version_string(verbose);
105-
print!("{}", version);
105+
cargo::drop_print!(config, "{}", version);
106106
return Ok(());
107107
}
108108
let prefix = if args.is_present("no-indent") {

src/bin/cargo/commands/verify_project.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ use crate::command_prelude::*;
33
use std::collections::HashMap;
44
use std::process;
55

6-
use cargo::print_json;
7-
86
pub fn cli() -> App {
97
subcommand("verify-project")
108
.about("Check correctness of crate manifest")
@@ -13,19 +11,15 @@ pub fn cli() -> App {
1311
}
1412

1513
pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
16-
fn fail(reason: &str, value: &str) -> ! {
14+
if let Err(e) = args.workspace(config) {
1715
let mut h = HashMap::new();
18-
h.insert(reason.to_string(), value.to_string());
19-
print_json(&h);
16+
h.insert("invalid".to_string(), e.to_string());
17+
config.shell().print_json(&h);
2018
process::exit(1)
2119
}
2220

23-
if let Err(e) = args.workspace(config) {
24-
fail("invalid", &e.to_string())
25-
}
26-
2721
let mut h = HashMap::new();
2822
h.insert("success".to_string(), "true".to_string());
29-
print_json(&h);
23+
config.shell().print_json(&h);
3024
Ok(())
3125
}

src/bin/cargo/commands/version.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
use crate::command_prelude::*;
2-
31
use crate::cli;
2+
use crate::command_prelude::*;
43

54
pub fn cli() -> App {
65
subcommand("version")
76
.about("Show version information")
87
.arg(opt("quiet", "No output printed to stdout").short("q"))
98
}
109

11-
pub fn exec(_config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
10+
pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
1211
let verbose = args.occurrences_of("verbose") > 0;
1312
let version = cli::get_version_string(verbose);
14-
print!("{}", version);
13+
cargo::drop_print!(config, "{}", version);
1514
Ok(())
1615
}

src/cargo/core/compiler/build_plan.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use serde::Serialize;
1414
use super::context::OutputFile;
1515
use super::{CompileKind, CompileMode, Context, Unit};
1616
use crate::core::TargetKind;
17-
use crate::util::{internal, CargoResult, ProcessBuilder};
17+
use crate::util::{internal, CargoResult, Config, ProcessBuilder};
1818

1919
#[derive(Debug, Serialize)]
2020
struct Invocation {
@@ -146,9 +146,9 @@ impl BuildPlan {
146146
self.plan.inputs = inputs;
147147
}
148148

149-
pub fn output_plan(self) {
149+
pub fn output_plan(self, config: &Config) {
150150
let encoded = serde_json::to_string(&self.plan).unwrap();
151-
println!("{}", encoded);
151+
crate::drop_println!(config, "{}", encoded);
152152
}
153153
}
154154

src/cargo/core/compiler/context/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
157157

158158
if build_plan {
159159
plan.set_inputs(self.build_plan_inputs()?);
160-
plan.output_plan();
160+
plan.output_plan(self.bcx.config);
161161
}
162162

163163
// Collect the result of the build into `self.compilation`.

src/cargo/core/compiler/job_queue.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ impl<'cfg> DrainState<'cfg> {
500500
plan.update(&module_name, &cmd, &filenames)?;
501501
}
502502
Message::Stdout(out) => {
503-
cx.bcx.config.shell().stdout_println(out);
503+
writeln!(cx.bcx.config.shell().out(), "{}", out)?;
504504
}
505505
Message::Stderr(err) => {
506506
let mut shell = cx.bcx.config.shell();
@@ -700,7 +700,7 @@ impl<'cfg> DrainState<'cfg> {
700700
success: error.is_none(),
701701
}
702702
.to_json_string();
703-
cx.bcx.config.shell().stdout_println(msg);
703+
writeln!(cx.bcx.config.shell().out(), "{}", msg)?;
704704
}
705705

706706
if let Some(e) = error {

src/cargo/core/compiler/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ fn compile<'cfg>(
146146
&unit.target,
147147
cx.files().message_cache_path(unit),
148148
cx.bcx.build_config.message_format,
149-
cx.bcx.config.shell().supports_color(),
149+
cx.bcx.config.shell().err_supports_color(),
150150
)
151151
} else {
152152
Work::noop()
@@ -1109,7 +1109,7 @@ struct OutputOptions {
11091109
impl OutputOptions {
11101110
fn new(cx: &Context<'_, '_>, unit: &Unit) -> OutputOptions {
11111111
let look_for_metadata_directive = cx.rmeta_required(unit);
1112-
let color = cx.bcx.config.shell().supports_color();
1112+
let color = cx.bcx.config.shell().err_supports_color();
11131113
let path = cx.files().message_cache_path(unit);
11141114
// Remove old cache, ignore ENOENT, which is the common case.
11151115
drop(fs::remove_file(&path));

src/cargo/core/compiler/timings.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ impl<'cfg> Timings<'cfg> {
245245
rmeta_time: unit_time.rmeta_time,
246246
}
247247
.to_json_string();
248-
self.config.shell().stdout_println(msg);
248+
crate::drop_println!(self.config, "{}", msg);
249249
}
250250
self.unit_times.push(unit_time);
251251
}

src/cargo/core/compiler/unit_graph.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,6 @@ pub fn emit_serialized_unit_graph(root_units: &[Unit], unit_graph: &UnitGraph) -
113113
let stdout = std::io::stdout();
114114
let mut lock = stdout.lock();
115115
serde_json::to_writer(&mut lock, &s)?;
116-
writeln!(lock)?;
116+
drop(writeln!(lock));
117117
Ok(())
118118
}

src/cargo/core/manifest.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ impl Manifest {
500500
pub fn print_teapot(&self, config: &Config) {
501501
if let Some(teapot) = self.im_a_teapot {
502502
if config.cli_unstable().print_im_a_teapot {
503-
println!("im-a-teapot = {}", teapot);
503+
crate::drop_println!(config, "im-a-teapot = {}", teapot);
504504
}
505505
}
506506
}

src/cargo/core/resolver/features.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -573,9 +573,13 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
573573
for ((pkg_id, dep_kind), features) in &self.activated_features {
574574
let r_features = self.resolve.features(*pkg_id);
575575
if !r_features.iter().eq(features.iter()) {
576-
eprintln!(
576+
crate::drop_eprintln!(
577+
self.ws.config(),
577578
"{}/{:?} features mismatch\nresolve: {:?}\nnew: {:?}\n",
578-
pkg_id, dep_kind, r_features, features
579+
pkg_id,
580+
dep_kind,
581+
r_features,
582+
features
579583
);
580584
found = true;
581585
}

0 commit comments

Comments
 (0)