Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixup stout/stderr on Windows #32184

Closed
wants to merge 3 commits into from
Closed

Conversation

ollie27
Copy link
Member

@ollie27 ollie27 commented Mar 10, 2016

WriteConsoleW can fail if called with a large buffer so we need to slice
any stdout/stderr output.
However the current slicing has a few problems:

  1. It slices by byte but still expects valid UTF-8.
  2. The slicing happens even when not outputting to a console.
  3. panic! output is not sliced.

This fixes these issues by moving the slice to right before
WriteConsoleW and slicing on a char boundary.

WriteConsoleW can fail if called with a large buffer so we need to slice
any stdout/stderr output.
However the current slicing has a few problems:
 1. It slices by byte but still expects valid UTF-8.
 2. The slicing happens even when not outputting to a console.
 3. panic! output is not sliced.

This fixes these issues by moving the slice to right before
WriteConsoleW and slicing on a char boundary.
@retep998
Copy link
Member

r? @alexcrichton

// [1]: https://tahoe-lafs.org/trac/tahoe-lafs/ticket/1232
// [2]: http://www.mail-archive.com/log4net-dev@logging.apache.org/msg00661.html
const OUT_MAX: usize = 8192;
let data_len;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could also be done by returning a tuple from the match block.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@retep998
Copy link
Member

Looks good to me.

cc #23344

// [1]: https://tahoe-lafs.org/trac/tahoe-lafs/ticket/1232
// [2]: http://www.mail-archive.com/log4net-dev@logging.apache.org/msg00661.html
const OUT_MAX: usize = 8192;
let (utf16, data_len) = match str::from_utf8(data).ok() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps this could do something like:

let len = cmp::min(data.len(), OUT_MAX);
let data = match str::from_utf8(&data[..len]) {
    Ok(s) => s,
    Err(ref e) if e.valid_up_to() == 0 => return Err(..),
    Err(e) => str::from_utf8(&s[..e.valid_up_to()]).unwrap(),
};
let data = ...;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the sense that it would:

  • Be the same performance for the "fast path"
  • Handle writing partially utf-8 data naturally
  • Not have to encode a let's-go-backwards loop

@alexcrichton
Copy link
Member

Can you add a test for this as well? The test in #30399 I think should be good to add.

This makes it output as much valid UTF-8 as it can then return failure.
@ollie27
Copy link
Member Author

ollie27 commented Mar 12, 2016

I've applied the suggested code changes however I'm not sure where to add a test as it will only make sense if output to a real console which isn't the case for run-pass for example.

@alexcrichton
Copy link
Member

Ah yeah that's a good point, sounds good to me then! Just to double check, but you've confirmed locally that this works as expected?

@bors: r+ bd80a53

@retep998
Copy link
Member

Technically the test could FreeConsole to make sure it isn't attached to any console and then call AllocConsole to give itself a brand new console to write to.

@ollie27
Copy link
Member Author

ollie27 commented Mar 12, 2016

Yeah I've tested and things like the following now work as expected:

fn main () {
    let v = vec![255u8; 5000];
    let s = String::from_utf8_lossy(&v);
    println!("{}", s);
}
fn main() {
    let s = unsafe { String::from_utf8_unchecked(vec![b'a'; 1 << 32]) };
    panic!("{}", s);
}

@bors
Copy link
Contributor

bors commented Mar 13, 2016

⌛ Testing commit bd80a53 with merge ce943eb...

bors added a commit that referenced this pull request Mar 13, 2016
Fixup stout/stderr on Windows

WriteConsoleW can fail if called with a large buffer so we need to slice
any stdout/stderr output.
However the current slicing has a few problems:
 1. It slices by byte but still expects valid UTF-8.
 2. The slicing happens even when not outputting to a console.
 3. panic! output is not sliced.

This fixes these issues by moving the slice to right before
WriteConsoleW and slicing on a char boundary.
@sfackler
Copy link
Member

Seems like bors messed up and didn't merge this? @alexcrichton

@alexcrichton
Copy link
Member

Looks like bors did indeed merge but github didn't detect it was merged, ah well.

@ollie27 ollie27 deleted the win_stdout branch May 2, 2016 18:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants