Skip to content

Commit

Permalink
Auto merge of rust-lang#117386 - roblabla:fix-switch-stdio-win7, r=Ch…
Browse files Browse the repository at this point in the history
…risDenton

Fix switch_stdout_to on Windows7

The `switch_stdout_to` test was broken on Windows7, as deleting the temporary test folder would fail since the `switch-stdout-output` file we redirected the stdout to is never closed, and it's impossible on Win7 to delete an opened file.

To fix this issue, we make `switch_stdout_to` return the previous handle. Using this, we add a new `switch_stdout_to` call at the end of the test to return the stdio handles to their original state, and recover the handle to the file we opened. This handle is automatically closed at the end of the function, which should allow the temporary test folder to be deleted properly.
  • Loading branch information
bors committed Nov 2, 2023
2 parents 42e1e12 + 4971e99 commit 46455dc
Showing 1 changed file with 21 additions and 3 deletions.
24 changes: 21 additions & 3 deletions library/std/tests/switch-stdout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,48 @@ use std::io::{Read, Write};

mod common;

#[cfg(windows)]
use std::os::windows::io::OwnedHandle;

#[cfg(unix)]
fn switch_stdout_to(file: File) {
use std::os::fd::OwnedFd;

#[cfg(unix)]
fn switch_stdout_to(file: OwnedFd) -> OwnedFd {
use std::os::unix::prelude::*;

extern "C" {
fn dup(old: i32) -> i32;
fn dup2(old: i32, new: i32) -> i32;
}

unsafe {
let orig_fd = dup(1);
assert_ne!(orig_fd, -1);
let res = OwnedFd::from_raw_fd(orig_fd);
assert_eq!(dup2(file.as_raw_fd(), 1), 1);
res
}
}

#[cfg(windows)]
fn switch_stdout_to(file: File) {
fn switch_stdout_to(file: OwnedHandle) -> OwnedHandle {
use std::os::windows::prelude::*;

extern "system" {
fn GetStdHandle(nStdHandle: u32) -> *mut u8;
fn SetStdHandle(nStdHandle: u32, handle: *mut u8) -> i32;
}

const STD_OUTPUT_HANDLE: u32 = (-11i32) as u32;
const INVALID_HANDLE_VALUE: *mut u8 = !0 as *mut u8;

unsafe {
let orig_hdl = GetStdHandle(STD_OUTPUT_HANDLE);
assert!(!orig_hdl.is_null() && orig_hdl != INVALID_HANDLE_VALUE);
let rc = SetStdHandle(STD_OUTPUT_HANDLE, file.into_raw_handle() as *mut _);
assert!(rc != 0);
OwnedHandle::from_raw_handle(orig_hdl as _)
}
}

Expand All @@ -43,10 +59,12 @@ fn switch_stdout() {
let mut stdout = std::io::stdout();
stdout.write(b"foo\n").unwrap();
stdout.flush().unwrap();
switch_stdout_to(f);
let orig_hdl = switch_stdout_to(f.into());
stdout.write(b"bar\n").unwrap();
stdout.flush().unwrap();

switch_stdout_to(orig_hdl);

let mut contents = String::new();
File::open(&path).unwrap().read_to_string(&mut contents).unwrap();
assert_eq!(contents, "bar\n");
Expand Down

0 comments on commit 46455dc

Please sign in to comment.