Skip to content

Commit 36c274a

Browse files
committed
Auto merge of #2084 - rust-lang:silence, r=RalfJung
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
2 parents 1abf2cf + 6dc6256 commit 36c274a

File tree

7 files changed

+79
-9
lines changed

7 files changed

+79
-9
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,10 @@ environment variable:
286286
This can be used to find which parts of your program are executing slowly under Miri.
287287
The profile is written out to a file with the prefix `<name>`, and can be processed
288288
using the tools in the repository https://github.com/rust-lang/measureme.
289+
* `-Zmiri-mute-stdout-stderr` silently ignores all writes to stdout and stderr,
290+
but reports to the program that it did actually write. This is useful when you
291+
are not interested in the actual program's output, but only want to see miri's
292+
errors and warnings.
289293
* `-Zmiri-panic-on-unsupported` will makes some forms of unsupported functionality,
290294
such as FFI and unsupported syscalls, panic within the context of the emulated
291295
application instead of raising an error within the context of Miri (and halting

src/bin/miri.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,9 @@ fn main() {
384384
miri_config.tag_raw = true;
385385
miri_config.check_number_validity = true;
386386
}
387+
"-Zmiri-mute-stdout-stderr" => {
388+
miri_config.mute_stdout_stderr = true;
389+
}
387390
"-Zmiri-track-raw-pointers" => {
388391
eprintln!(
389392
"WARNING: -Zmiri-track-raw-pointers has been renamed to -Zmiri-tag-raw-pointers, the old name is deprecated."

src/eval.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ pub struct MiriConfig {
116116
/// Whether to enforce "strict provenance" rules. Enabling this means int2ptr casts return
117117
/// pointers with an invalid provenance, i.e., not valid for any memory access.
118118
pub strict_provenance: bool,
119+
/// Whether to ignore any output by the program. This is helpful when debugging miri
120+
/// as its messages don't get intermingled with the program messages.
121+
pub mute_stdout_stderr: bool,
119122
}
120123

121124
impl Default for MiriConfig {
@@ -142,6 +145,7 @@ impl Default for MiriConfig {
142145
panic_on_unsupported: false,
143146
backtrace_style: BacktraceStyle::Short,
144147
strict_provenance: false,
148+
mute_stdout_stderr: false,
145149
}
146150
}
147151
}

src/machine.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use rustc_span::symbol::{sym, Symbol};
2828
use rustc_target::abi::Size;
2929
use rustc_target::spec::abi::Abi;
3030

31-
use crate::*;
31+
use crate::{*, shims::posix::FileHandler};
3232

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

292292
/// Failure rate of compare_exchange_weak, between 0.0 and 1.0
293293
pub(crate) cmpxchg_weak_failure_rate: f64,
294+
295+
/// Corresponds to -Zmiri-mute-stdout-stderr and doesn't write the output but acts as if it succeeded.
296+
pub(crate) mute_stdout_stderr: bool,
294297
}
295298

296299
impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
@@ -327,7 +330,7 @@ impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
327330
validate: config.validate,
328331
enforce_number_validity: config.check_number_validity,
329332
enforce_abi: config.check_abi,
330-
file_handler: Default::default(),
333+
file_handler: FileHandler::new(config.mute_stdout_stderr),
331334
dir_handler: Default::default(),
332335
time_anchor: Instant::now(),
333336
layouts,
@@ -344,6 +347,7 @@ impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
344347
tracked_alloc_ids: config.tracked_alloc_ids.clone(),
345348
check_alignment: config.check_alignment,
346349
cmpxchg_weak_failure_rate: config.cmpxchg_weak_failure_rate,
350+
mute_stdout_stderr: config.mute_stdout_stderr,
347351
}
348352
}
349353

src/shims/posix/fs.rs

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -251,22 +251,70 @@ impl FileDescriptor for io::Stderr {
251251
}
252252
}
253253

254+
#[derive(Debug)]
255+
struct DummyOutput;
256+
257+
impl FileDescriptor for DummyOutput {
258+
fn as_file_handle<'tcx>(&self) -> InterpResult<'tcx, &FileHandle> {
259+
throw_unsup_format!("stderr and stdout cannot be used as FileHandle");
260+
}
261+
262+
fn read<'tcx>(
263+
&mut self,
264+
_communicate_allowed: bool,
265+
_bytes: &mut [u8],
266+
) -> InterpResult<'tcx, io::Result<usize>> {
267+
throw_unsup_format!("cannot read from stderr or stdout");
268+
}
269+
270+
fn write<'tcx>(
271+
&self,
272+
_communicate_allowed: bool,
273+
bytes: &[u8],
274+
) -> InterpResult<'tcx, io::Result<usize>> {
275+
// We just don't write anything, but report to the user that we did.
276+
Ok(Ok(bytes.len()))
277+
}
278+
279+
fn seek<'tcx>(
280+
&mut self,
281+
_communicate_allowed: bool,
282+
_offset: SeekFrom,
283+
) -> InterpResult<'tcx, io::Result<u64>> {
284+
throw_unsup_format!("cannot seek on stderr or stdout");
285+
}
286+
287+
fn close<'tcx>(
288+
self: Box<Self>,
289+
_communicate_allowed: bool,
290+
) -> InterpResult<'tcx, io::Result<i32>> {
291+
throw_unsup_format!("stderr and stdout cannot be closed");
292+
}
293+
294+
fn dup<'tcx>(&mut self) -> io::Result<Box<dyn FileDescriptor>> {
295+
Ok(Box::new(DummyOutput))
296+
}
297+
}
298+
254299
#[derive(Debug)]
255300
pub struct FileHandler {
256301
handles: BTreeMap<i32, Box<dyn FileDescriptor>>,
257302
}
258303

259-
impl<'tcx> Default for FileHandler {
260-
fn default() -> Self {
304+
impl<'tcx> FileHandler {
305+
pub(crate) fn new(mute_stdout_stderr: bool) -> FileHandler {
261306
let mut handles: BTreeMap<_, Box<dyn FileDescriptor>> = BTreeMap::new();
262-
handles.insert(0i32, Box::new(io::stdin()));
263-
handles.insert(1i32, Box::new(io::stdout()));
307+
if mute_stdout_stderr {
308+
handles.insert(0i32, Box::new(DummyOutput));
309+
handles.insert(1i32, Box::new(DummyOutput));
310+
} else {
311+
handles.insert(0i32, Box::new(io::stdin()));
312+
handles.insert(1i32, Box::new(io::stdout()));
313+
}
264314
handles.insert(2i32, Box::new(io::stderr()));
265315
FileHandler { handles }
266316
}
267-
}
268317

269-
impl<'tcx> FileHandler {
270318
fn insert_fd(&mut self, file_handle: Box<dyn FileDescriptor>) -> i32 {
271319
self.insert_fd_with_min_fd(file_handle, 0)
272320
}

src/shims/windows/dlsym.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
7575
use std::io::{self, Write};
7676

7777
let buf_cont = this.read_bytes_ptr(buf, Size::from_bytes(u64::from(n)))?;
78-
let res = if handle == -11 {
78+
let res = if this.machine.mute_stdout_stderr {
79+
Ok(buf_cont.len())
80+
} else if handle == -11 {
7981
io::stdout().write(buf_cont)
8082
} else {
8183
io::stderr().write(buf_cont)

tests/run-pass/hide_stdout.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// compile-flags: -Zmiri-mute-stdout-stderr
2+
3+
fn main() {
4+
println!("cake");
5+
}

0 commit comments

Comments
 (0)