Skip to content

Commit f5a3039

Browse files
authored
Rollup merge of #110783 - dtolnay:safeprint, r=petrochenkov
Fix ICE on --print=... i/o errors `rustc --print=cfg > /dev/full` **Before:** ICE (see below) **After:** exits quietly with code 1. ```console thread 'rustc' panicked at 'failed printing to stdout: No space left on device (os error 28)', library/std/src/io/stdio.rs:1019:9 stack backtrace: 0: 0x7ffa84d68f33 - std::backtrace_rs::backtrace::libunwind::trace::h527d8d64d53ade2d at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5 1: 0x7ffa84d68f33 - std::backtrace_rs::backtrace::trace_unsynchronized::hfb55b01517dd6379 at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5 2: 0x7ffa84d68f33 - std::sys_common::backtrace::_print_fmt::hd134e914eea0bd97 at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/sys_common/backtrace.rs:65:5 3: 0x7ffa84d68f33 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h1480db11ec399d77 at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/sys_common/backtrace.rs:44:22 4: 0x7ffa84dc9d4f - core::fmt::write::h67ec4c4171c92b26 at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/core/src/fmt/mod.rs:1247:17 5: 0x7ffa84d5bed1 - std::io::Write::write_fmt::h3b12aef0fff2463b at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/io/mod.rs:1712:15 6: 0x7ffa84d68d45 - std::sys_common::backtrace::_print::h584400135abdbd51 at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/sys_common/backtrace.rs:47:5 7: 0x7ffa84d68d45 - std::sys_common::backtrace::print::hce41d3c8bd91096b at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/sys_common/backtrace.rs:34:9 8: 0x7ffa84d6b84f - std::panicking::default_hook::{{closure}}::h2043b657a3791225 9: 0x7ffa84d6b507 - std::panicking::default_hook::h99252b8d3dd5719c at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/panicking.rs:293:9 10: 0x7ffa87fdf915 - <rustc_driver_impl[d30cd2737d9d343a]::DEFAULT_HOOK::{closure#0}::{closure#0} as core[cc19a662f3570270]::ops::function::FnOnce<(&core[cc19a662f3570270]::panic::panic_info::PanicInfo,)>>::call_once::{shim:vtable#0} 11: 0x7ffa84d6c005 - <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call::h222a2b674b9f4762 at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/alloc/src/boxed.rs:1976:9 12: 0x7ffa84d6c005 - std::panicking::rust_panic_with_hook::h7f49b36bf7f8ff77 at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/panicking.rs:704:13 13: 0x7ffa84d6bd73 - std::panicking::begin_panic_handler::{{closure}}::haa23a7352589e31e at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/panicking.rs:595:13 14: 0x7ffa84d69376 - std::sys_common::backtrace::__rust_end_short_backtrace::h3d0cf6e3c96e3fe9 at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/sys_common/backtrace.rs:150:18 15: 0x7ffa84d6ba72 - rust_begin_unwind at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/panicking.rs:584:5 16: 0x7ffa84dc5fe3 - core::panicking::panic_fmt::hf4b4ea11e3fdb110 at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/core/src/panicking.rs:67:14 17: 0x7ffa84d5aa07 - std::io::stdio::print_to::h55760b9ede306280 at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/io/stdio.rs:1019:9 18: 0x7ffa84d5aa07 - std::io::stdio::_print::h93deb6099db33eab at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/io/stdio.rs:1095:5 19: 0x7ffa871e163b - rustc_driver_impl[d30cd2737d9d343a]::print_crate_info 20: 0x7ffa87fb8e01 - rustc_span[9551eaa044f53f4f]::set_source_map::<(), rustc_interface[c2b70c9b1dae0906]::interface::run_compiler<(), rustc_driver_impl[d30cd2737d9d343a]::run_compiler::{closure#0}>::{closure#0}::{closure#0}> 21: 0x7ffa87fb6d59 - std[71a32ca0600a6a04]::sys_common::backtrace::__rust_begin_short_backtrace::<rustc_interface[c2b70c9b1dae0906]::util::run_in_thread_pool_with_globals<rustc_interface[c2b70c9b1dae0906]::interface::run_compiler<(), rustc_driver_impl[d30cd2737d9d343a]::run_compiler::{closure#0}>::{closure#0}, ()>::{closure#0}::{closure#0}, ()> 22: 0x7ffa87fe25b4 - std[71a32ca0600a6a04]::panicking::try::<(), core[cc19a662f3570270]::panic::unwind_safe::AssertUnwindSafe<<std[71a32ca0600a6a04]::thread::Builder>::spawn_unchecked_<rustc_interface[c2b70c9b1dae0906]::util::run_in_thread_pool_with_globals<rustc_interface[c2b70c9b1dae0906]::interface::run_compiler<(), rustc_driver_impl[d30cd2737d9d343a]::run_compiler::{closure#0}>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>::{closure#1}::{closure#0}>> 23: 0x7ffa87fb0cf1 - <<std[71a32ca0600a6a04]::thread::Builder>::spawn_unchecked_<rustc_interface[c2b70c9b1dae0906]::util::run_in_thread_pool_with_globals<rustc_interface[c2b70c9b1dae0906]::interface::run_compiler<(), rustc_driver_impl[d30cd2737d9d343a]::run_compiler::{closure#0}>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>::{closure#1} as core[cc19a662f3570270]::ops::function::FnOnce<()>>::call_once::{shim:vtable#0} 24: 0x7ffa84d763e5 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::hf15d802f31f86225 at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/alloc/src/boxed.rs:1962:9 25: 0x7ffa84d763e5 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::hac564355b46c52d6 at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/alloc/src/boxed.rs:1962:9 26: 0x7ffa84d763e5 - std::sys::unix::thread::Thread::new::thread_start::h86fb3aedb7811f07 at /rustc/7f94b314cead7059a71a265a8b64905ef2511796/library/std/src/sys/unix/thread.rs:108:17 27: 0x7ffa84a94b43 - start_thread at ./nptl/pthread_create.c:442:8 28: 0x7ffa84b26a00 - clone3 at ./misc/../sysdeps/unix/sysv/linux/x86_64/clone3.S:81 29: 0x0 - <unknown> error: the compiler unexpectedly panicked. this is a bug. note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md note: rustc 1.71.0-nightly (7f94b31 2023-04-23) running on x86_64-unknown-linux-gnu query stack during panic: end of query stack ```
2 parents 95e9f68 + 040e1b6 commit f5a3039

File tree

2 files changed

+68
-40
lines changed

2 files changed

+68
-40
lines changed

compiler/rustc_driver_impl/src/lib.rs

+48-40
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,16 @@ use std::str;
5858
use std::sync::LazyLock;
5959
use std::time::Instant;
6060

61+
// This import blocks the use of panicking `print` and `println` in all the code
62+
// below. Please use `safe_print` and `safe_println` to avoid ICE when
63+
// encountering an I/O error during print.
64+
#[allow(unused_imports)]
65+
use std::{compile_error as print, compile_error as println};
66+
6167
pub mod args;
6268
pub mod pretty;
69+
#[macro_use]
70+
mod print;
6371
mod session_diagnostics;
6472

6573
use crate::session_diagnostics::{
@@ -511,7 +519,7 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
511519
if io::stdout().is_terminal() {
512520
show_content_with_pager(&text);
513521
} else {
514-
print!("{text}");
522+
safe_print!("{text}");
515523
}
516524
}
517525
Err(InvalidErrorCode) => {
@@ -547,7 +555,7 @@ fn show_content_with_pager(content: &str) {
547555
// If pager fails for whatever reason, we should still print the content
548556
// to standard output
549557
if fallback_to_println {
550-
print!("{content}");
558+
safe_print!("{content}");
551559
}
552560
}
553561

@@ -601,7 +609,7 @@ pub fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) -> Co
601609
let path = &(*ifile);
602610
let mut v = Vec::new();
603611
locator::list_file_metadata(&sess.target, path, metadata_loader, &mut v).unwrap();
604-
println!("{}", String::from_utf8(v).unwrap());
612+
safe_println!("{}", String::from_utf8(v).unwrap());
605613
}
606614
Input::Str { .. } => {
607615
early_error(ErrorOutputType::default(), "cannot list metadata for stdin");
@@ -642,12 +650,12 @@ fn print_crate_info(
642650
TargetList => {
643651
let mut targets = rustc_target::spec::TARGETS.to_vec();
644652
targets.sort_unstable();
645-
println!("{}", targets.join("\n"));
653+
safe_println!("{}", targets.join("\n"));
646654
}
647-
Sysroot => println!("{}", sess.sysroot.display()),
648-
TargetLibdir => println!("{}", sess.target_tlib_path.dir.display()),
655+
Sysroot => safe_println!("{}", sess.sysroot.display()),
656+
TargetLibdir => safe_println!("{}", sess.target_tlib_path.dir.display()),
649657
TargetSpec => {
650-
println!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap());
658+
safe_println!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap());
651659
}
652660
AllTargetSpecs => {
653661
let mut targets = BTreeMap::new();
@@ -656,7 +664,7 @@ fn print_crate_info(
656664
let target = Target::expect_builtin(&triple);
657665
targets.insert(name, target.to_json());
658666
}
659-
println!("{}", serde_json::to_string_pretty(&targets).unwrap());
667+
safe_println!("{}", serde_json::to_string_pretty(&targets).unwrap());
660668
}
661669
FileNames | CrateName => {
662670
let Some(attrs) = attrs.as_ref() else {
@@ -666,14 +674,14 @@ fn print_crate_info(
666674
let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess);
667675
let id = rustc_session::output::find_crate_name(sess, attrs);
668676
if *req == PrintRequest::CrateName {
669-
println!("{id}");
677+
safe_println!("{id}");
670678
continue;
671679
}
672680
let crate_types = collect_crate_types(sess, attrs);
673681
for &style in &crate_types {
674682
let fname =
675683
rustc_session::output::filename_for_input(sess, style, id, &t_outputs);
676-
println!("{}", fname.file_name().unwrap().to_string_lossy());
684+
safe_println!("{}", fname.file_name().unwrap().to_string_lossy());
677685
}
678686
}
679687
Cfg => {
@@ -707,13 +715,13 @@ fn print_crate_info(
707715

708716
cfgs.sort();
709717
for cfg in cfgs {
710-
println!("{cfg}");
718+
safe_println!("{cfg}");
711719
}
712720
}
713721
CallingConventions => {
714722
let mut calling_conventions = rustc_target::spec::abi::all_names();
715723
calling_conventions.sort_unstable();
716-
println!("{}", calling_conventions.join("\n"));
724+
safe_println!("{}", calling_conventions.join("\n"));
717725
}
718726
RelocationModels
719727
| CodeModels
@@ -733,7 +741,7 @@ fn print_crate_info(
733741
let stable = sess.target.options.supported_split_debuginfo.contains(split);
734742
let unstable_ok = sess.unstable_options();
735743
if stable || unstable_ok {
736-
println!("{split}");
744+
safe_println!("{split}");
737745
}
738746
}
739747
}
@@ -770,14 +778,14 @@ pub fn version_at_macro_invocation(
770778
) {
771779
let verbose = matches.opt_present("verbose");
772780

773-
println!("{binary} {version}");
781+
safe_println!("{binary} {version}");
774782

775783
if verbose {
776-
println!("binary: {binary}");
777-
println!("commit-hash: {commit_hash}");
778-
println!("commit-date: {commit_date}");
779-
println!("host: {}", config::host_triple());
780-
println!("release: {release}");
784+
safe_println!("binary: {binary}");
785+
safe_println!("commit-hash: {commit_hash}");
786+
safe_println!("commit-date: {commit_date}");
787+
safe_println!("host: {}", config::host_triple());
788+
safe_println!("release: {release}");
781789

782790
let debug_flags = matches.opt_strs("Z");
783791
let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
@@ -807,7 +815,7 @@ fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) {
807815
} else {
808816
""
809817
};
810-
println!(
818+
safe_println!(
811819
"{options}{at_path}\nAdditional help:
812820
-C help Print codegen options
813821
-W help \
@@ -820,7 +828,7 @@ fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) {
820828
}
821829

822830
fn print_wall_help() {
823-
println!(
831+
safe_println!(
824832
"
825833
The flag `-Wall` does not exist in `rustc`. Most useful lints are enabled by
826834
default. Use `rustc -W help` to see all available lints. It's more common to put
@@ -832,7 +840,7 @@ the command line flag directly.
832840

833841
/// Write to stdout lint command options, together with a list of all available lints
834842
pub fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_plugins: bool) {
835-
println!(
843+
safe_println!(
836844
"
837845
Available lint options:
838846
-W <foo> Warn about <foo>
@@ -877,21 +885,21 @@ Available lint options:
877885
s
878886
};
879887

880-
println!("Lint checks provided by rustc:\n");
888+
safe_println!("Lint checks provided by rustc:\n");
881889

882890
let print_lints = |lints: Vec<&Lint>| {
883-
println!(" {} {:7.7} {}", padded("name"), "default", "meaning");
884-
println!(" {} {:7.7} {}", padded("----"), "-------", "-------");
891+
safe_println!(" {} {:7.7} {}", padded("name"), "default", "meaning");
892+
safe_println!(" {} {:7.7} {}", padded("----"), "-------", "-------");
885893
for lint in lints {
886894
let name = lint.name_lower().replace('_', "-");
887-
println!(
895+
safe_println!(
888896
" {} {:7.7} {}",
889897
padded(&name),
890898
lint.default_level(sess.edition()).as_str(),
891899
lint.desc
892900
);
893901
}
894-
println!("\n");
902+
safe_println!("\n");
895903
};
896904

897905
print_lints(builtin);
@@ -912,14 +920,14 @@ Available lint options:
912920
s
913921
};
914922

915-
println!("Lint groups provided by rustc:\n");
923+
safe_println!("Lint groups provided by rustc:\n");
916924

917925
let print_lint_groups = |lints: Vec<(&'static str, Vec<LintId>)>, all_warnings| {
918-
println!(" {} sub-lints", padded("name"));
919-
println!(" {} ---------", padded("----"));
926+
safe_println!(" {} sub-lints", padded("name"));
927+
safe_println!(" {} ---------", padded("----"));
920928

921929
if all_warnings {
922-
println!(" {} all lints that are set to issue warnings", padded("warnings"));
930+
safe_println!(" {} all lints that are set to issue warnings", padded("warnings"));
923931
}
924932

925933
for (name, to) in lints {
@@ -929,26 +937,26 @@ Available lint options:
929937
.map(|x| x.to_string().replace('_', "-"))
930938
.collect::<Vec<String>>()
931939
.join(", ");
932-
println!(" {} {}", padded(&name), desc);
940+
safe_println!(" {} {}", padded(&name), desc);
933941
}
934-
println!("\n");
942+
safe_println!("\n");
935943
};
936944

937945
print_lint_groups(builtin_groups, true);
938946

939947
match (loaded_plugins, plugin.len(), plugin_groups.len()) {
940948
(false, 0, _) | (false, _, 0) => {
941-
println!("Lint tools like Clippy can provide additional lints and lint groups.");
949+
safe_println!("Lint tools like Clippy can provide additional lints and lint groups.");
942950
}
943951
(false, ..) => panic!("didn't load lint plugins but got them anyway!"),
944-
(true, 0, 0) => println!("This crate does not load any lint plugins or lint groups."),
952+
(true, 0, 0) => safe_println!("This crate does not load any lint plugins or lint groups."),
945953
(true, l, g) => {
946954
if l > 0 {
947-
println!("Lint checks provided by plugins loaded by this crate:\n");
955+
safe_println!("Lint checks provided by plugins loaded by this crate:\n");
948956
print_lints(plugin);
949957
}
950958
if g > 0 {
951-
println!("Lint groups provided by plugins loaded by this crate:\n");
959+
safe_println!("Lint groups provided by plugins loaded by this crate:\n");
952960
print_lint_groups(plugin_groups, false);
953961
}
954962
}
@@ -996,12 +1004,12 @@ pub fn describe_flag_categories(matches: &Matches) -> bool {
9961004
}
9971005

9981006
fn describe_debug_flags() {
999-
println!("\nAvailable options:\n");
1007+
safe_println!("\nAvailable options:\n");
10001008
print_flag_list("-Z", config::Z_OPTIONS);
10011009
}
10021010

10031011
fn describe_codegen_flags() {
1004-
println!("\nAvailable codegen options:\n");
1012+
safe_println!("\nAvailable codegen options:\n");
10051013
print_flag_list("-C", config::CG_OPTIONS);
10061014
}
10071015

@@ -1012,7 +1020,7 @@ fn print_flag_list<T>(
10121020
let max_len = flag_list.iter().map(|&(name, _, _, _)| name.chars().count()).max().unwrap_or(0);
10131021

10141022
for &(name, _, _, desc) in flag_list {
1015-
println!(
1023+
safe_println!(
10161024
" {} {:>width$}=val -- {}",
10171025
cmdline_opt,
10181026
name.replace('_', "-"),
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use std::fmt;
2+
use std::io::{self, Write as _};
3+
4+
macro_rules! safe_print {
5+
($($arg:tt)*) => {{
6+
$crate::print::print(std::format_args!($($arg)*));
7+
}};
8+
}
9+
10+
macro_rules! safe_println {
11+
($($arg:tt)*) => {
12+
safe_print!("{}\n", std::format_args!($($arg)*))
13+
};
14+
}
15+
16+
pub(crate) fn print(args: fmt::Arguments<'_>) {
17+
if let Err(_) = io::stdout().write_fmt(args) {
18+
rustc_errors::FatalError.raise();
19+
}
20+
}

0 commit comments

Comments
 (0)