From b991bbe2d0f148d25d00a8c17bfa6304d1b1ae5a Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Mon, 19 May 2014 14:37:52 -0700 Subject: [PATCH] Reset the terminal color before the newline for diagnostics When printing colored diagnostics, we need to reset the terminal before emitting the newline, not after. Otherwise it gets line-buffered and the color won't reset until the next line is printed or the compiler exits. Normally this isn't a problem, but when running rustc in parallel with other processes (e.g. `make -j4`) this can cause the color to leak to other lines. --- src/libsyntax/diagnostic.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 1a07393f9fc..3eb6f40ba53 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -232,8 +232,27 @@ fn print_maybe_styled(w: &mut EmitterWriter, match w.dst { Terminal(ref mut t) => { try!(t.attr(color)); - try!(t.write_str(msg)); - try!(t.reset()); + // If `msg` ends in a newline, we need to reset the color before + // the newline. We're making the assumption that we end up writing + // to a `LineBufferedWriter`, which means that emitting the reset + // after the newline ends up buffering the reset until we print + // another line or exit. Buffering the reset is a problem if we're + // sharing the terminal with any other programs (e.g. other rustc + // instances via `make -jN`). + // + // Note that if `msg` contains any internal newlines, this will + // result in the `LineBufferedWriter` flushing twice instead of + // once, which still leaves the opportunity for interleaved output + // to be miscolored. We assume this is rare enough that we don't + // have to worry about it. + if msg.ends_with("\n") { + try!(t.write_str(msg.slice_to(msg.len()-1))); + try!(t.reset()); + try!(t.write_str("\n")); + } else { + try!(t.write_str(msg)); + try!(t.reset()); + } Ok(()) } Raw(ref mut w) => {