Skip to content

Commit

Permalink
Auto merge of #2084 - rust-lang:silence, r=RalfJung
Browse files Browse the repository at this point in the history
Add a command line flag to avoid printing to stdout and stderr

This is practical for tests that don't actually care about the output and thus don't want it intermingled with miri's warnings, errors or ICEs

fixes #2083
  • Loading branch information
bors committed May 10, 2022
2 parents 1abf2cf + 6dc6256 commit 36c274a
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 9 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,10 @@ environment variable:
This can be used to find which parts of your program are executing slowly under Miri.
The profile is written out to a file with the prefix `<name>`, and can be processed
using the tools in the repository https://github.com/rust-lang/measureme.
* `-Zmiri-mute-stdout-stderr` silently ignores all writes to stdout and stderr,
but reports to the program that it did actually write. This is useful when you
are not interested in the actual program's output, but only want to see miri's
errors and warnings.
* `-Zmiri-panic-on-unsupported` will makes some forms of unsupported functionality,
such as FFI and unsupported syscalls, panic within the context of the emulated
application instead of raising an error within the context of Miri (and halting
Expand Down
3 changes: 3 additions & 0 deletions src/bin/miri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,9 @@ fn main() {
miri_config.tag_raw = true;
miri_config.check_number_validity = true;
}
"-Zmiri-mute-stdout-stderr" => {
miri_config.mute_stdout_stderr = true;
}
"-Zmiri-track-raw-pointers" => {
eprintln!(
"WARNING: -Zmiri-track-raw-pointers has been renamed to -Zmiri-tag-raw-pointers, the old name is deprecated."
Expand Down
4 changes: 4 additions & 0 deletions src/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ pub struct MiriConfig {
/// Whether to enforce "strict provenance" rules. Enabling this means int2ptr casts return
/// pointers with an invalid provenance, i.e., not valid for any memory access.
pub strict_provenance: bool,
/// Whether to ignore any output by the program. This is helpful when debugging miri
/// as its messages don't get intermingled with the program messages.
pub mute_stdout_stderr: bool,
}

impl Default for MiriConfig {
Expand All @@ -142,6 +145,7 @@ impl Default for MiriConfig {
panic_on_unsupported: false,
backtrace_style: BacktraceStyle::Short,
strict_provenance: false,
mute_stdout_stderr: false,
}
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use rustc_span::symbol::{sym, Symbol};
use rustc_target::abi::Size;
use rustc_target::spec::abi::Abi;

use crate::*;
use crate::{*, shims::posix::FileHandler};

// Some global facts about the emulated machine.
pub const PAGE_SIZE: u64 = 4 * 1024; // FIXME: adjust to target architecture
Expand Down Expand Up @@ -291,6 +291,9 @@ pub struct Evaluator<'mir, 'tcx> {

/// Failure rate of compare_exchange_weak, between 0.0 and 1.0
pub(crate) cmpxchg_weak_failure_rate: f64,

/// Corresponds to -Zmiri-mute-stdout-stderr and doesn't write the output but acts as if it succeeded.
pub(crate) mute_stdout_stderr: bool,
}

impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
Expand Down Expand Up @@ -327,7 +330,7 @@ impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
validate: config.validate,
enforce_number_validity: config.check_number_validity,
enforce_abi: config.check_abi,
file_handler: Default::default(),
file_handler: FileHandler::new(config.mute_stdout_stderr),
dir_handler: Default::default(),
time_anchor: Instant::now(),
layouts,
Expand All @@ -344,6 +347,7 @@ impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
tracked_alloc_ids: config.tracked_alloc_ids.clone(),
check_alignment: config.check_alignment,
cmpxchg_weak_failure_rate: config.cmpxchg_weak_failure_rate,
mute_stdout_stderr: config.mute_stdout_stderr,
}
}

Expand Down
60 changes: 54 additions & 6 deletions src/shims/posix/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,22 +251,70 @@ impl FileDescriptor for io::Stderr {
}
}

#[derive(Debug)]
struct DummyOutput;

impl FileDescriptor for DummyOutput {
fn as_file_handle<'tcx>(&self) -> InterpResult<'tcx, &FileHandle> {
throw_unsup_format!("stderr and stdout cannot be used as FileHandle");
}

fn read<'tcx>(
&mut self,
_communicate_allowed: bool,
_bytes: &mut [u8],
) -> InterpResult<'tcx, io::Result<usize>> {
throw_unsup_format!("cannot read from stderr or stdout");
}

fn write<'tcx>(
&self,
_communicate_allowed: bool,
bytes: &[u8],
) -> InterpResult<'tcx, io::Result<usize>> {
// We just don't write anything, but report to the user that we did.
Ok(Ok(bytes.len()))
}

fn seek<'tcx>(
&mut self,
_communicate_allowed: bool,
_offset: SeekFrom,
) -> InterpResult<'tcx, io::Result<u64>> {
throw_unsup_format!("cannot seek on stderr or stdout");
}

fn close<'tcx>(
self: Box<Self>,
_communicate_allowed: bool,
) -> InterpResult<'tcx, io::Result<i32>> {
throw_unsup_format!("stderr and stdout cannot be closed");
}

fn dup<'tcx>(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
Ok(Box::new(DummyOutput))
}
}

#[derive(Debug)]
pub struct FileHandler {
handles: BTreeMap<i32, Box<dyn FileDescriptor>>,
}

impl<'tcx> Default for FileHandler {
fn default() -> Self {
impl<'tcx> FileHandler {
pub(crate) fn new(mute_stdout_stderr: bool) -> FileHandler {
let mut handles: BTreeMap<_, Box<dyn FileDescriptor>> = BTreeMap::new();
handles.insert(0i32, Box::new(io::stdin()));
handles.insert(1i32, Box::new(io::stdout()));
if mute_stdout_stderr {
handles.insert(0i32, Box::new(DummyOutput));
handles.insert(1i32, Box::new(DummyOutput));
} else {
handles.insert(0i32, Box::new(io::stdin()));
handles.insert(1i32, Box::new(io::stdout()));
}
handles.insert(2i32, Box::new(io::stderr()));
FileHandler { handles }
}
}

impl<'tcx> FileHandler {
fn insert_fd(&mut self, file_handle: Box<dyn FileDescriptor>) -> i32 {
self.insert_fd_with_min_fd(file_handle, 0)
}
Expand Down
4 changes: 3 additions & 1 deletion src/shims/windows/dlsym.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
use std::io::{self, Write};

let buf_cont = this.read_bytes_ptr(buf, Size::from_bytes(u64::from(n)))?;
let res = if handle == -11 {
let res = if this.machine.mute_stdout_stderr {
Ok(buf_cont.len())
} else if handle == -11 {
io::stdout().write(buf_cont)
} else {
io::stderr().write(buf_cont)
Expand Down
5 changes: 5 additions & 0 deletions tests/run-pass/hide_stdout.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// compile-flags: -Zmiri-mute-stdout-stderr

fn main() {
println!("cake");
}

0 comments on commit 36c274a

Please sign in to comment.