Skip to content

Commit a8ffc7f

Browse files
committed
Tests for unsound Windows file methods
1 parent 3ae47e7 commit a8ffc7f

File tree

3 files changed

+101
-0
lines changed

3 files changed

+101
-0
lines changed

library/std/src/sys/windows/handle.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#![unstable(issue = "none", feature = "windows_handle")]
22

3+
#[cfg(test)]
4+
mod tests;
5+
36
use crate::cmp;
47
use crate::io::{self, ErrorKind, IoSlice, IoSliceMut, Read, ReadBuf};
58
use crate::mem;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
use crate::sys::pipe::{anon_pipe, Pipes};
2+
use crate::{thread, time};
3+
4+
/// Test the synchronous fallback for overlapped I/O.
5+
#[test]
6+
fn overlapped_handle_fallback() {
7+
// Create some pipes. `ours` will be asynchronous.
8+
let Pipes { ours, theirs } = anon_pipe(true, false).unwrap();
9+
10+
let async_readable = ours.into_handle();
11+
let sync_writeable = theirs.into_handle();
12+
13+
thread::scope(|_| {
14+
thread::sleep(time::Duration::from_millis(100));
15+
sync_writeable.write(b"hello world!").unwrap();
16+
});
17+
18+
// The pipe buffer starts empty so reading won't complete synchronously unless
19+
// our fallback path works.
20+
let mut buffer = [0u8; 1024];
21+
async_readable.read(&mut buffer).unwrap();
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// run-fail
2+
// only-windows
3+
4+
fn main() {
5+
use std::fs;
6+
use std::io::prelude::*;
7+
use std::os::windows::prelude::*;
8+
use std::ptr;
9+
use std::sync::Arc;
10+
use std::thread;
11+
use std::time::Duration;
12+
13+
const FILE_FLAG_OVERLAPPED: u32 = 0x40000000;
14+
15+
fn create_pipe_server(path: &str) -> fs::File {
16+
let mut path0 = path.as_bytes().to_owned();
17+
path0.push(0);
18+
extern "system" {
19+
fn CreateNamedPipeA(
20+
lpName: *const u8,
21+
dwOpenMode: u32,
22+
dwPipeMode: u32,
23+
nMaxInstances: u32,
24+
nOutBufferSize: u32,
25+
nInBufferSize: u32,
26+
nDefaultTimeOut: u32,
27+
lpSecurityAttributes: *mut u8,
28+
) -> RawHandle;
29+
}
30+
31+
unsafe {
32+
let h = CreateNamedPipeA(path0.as_ptr(), 3, 0, 1, 0, 0, 0, ptr::null_mut());
33+
assert_ne!(h as isize, -1);
34+
fs::File::from_raw_handle(h)
35+
}
36+
}
37+
38+
let path = "\\\\.\\pipe\\repro";
39+
let mut server = create_pipe_server(path);
40+
41+
let client = Arc::new(
42+
fs::OpenOptions::new().custom_flags(FILE_FLAG_OVERLAPPED).read(true).open(path).unwrap(),
43+
);
44+
45+
let spawn_read = |is_first: bool| {
46+
thread::spawn({
47+
let f = client.clone();
48+
move || {
49+
let mut buf = [0xcc; 1];
50+
let mut f = f.as_ref();
51+
f.read(&mut buf).unwrap();
52+
if is_first {
53+
assert_ne!(buf[0], 0xcc);
54+
} else {
55+
let b = buf[0]; // capture buf[0]
56+
thread::sleep(Duration::from_millis(200));
57+
58+
// In this test, success is indicated by failing.
59+
if buf[0] == b {
60+
panic!("Success!");
61+
}
62+
}
63+
}
64+
})
65+
};
66+
67+
let t1 = spawn_read(true);
68+
thread::sleep(Duration::from_millis(20));
69+
let t2 = spawn_read(false);
70+
thread::sleep(Duration::from_millis(100));
71+
let _ = server.write(b"x");
72+
thread::sleep(Duration::from_millis(100));
73+
let _ = server.write(b"y");
74+
let _ = t1.join();
75+
let _ = t2.join();
76+
}

0 commit comments

Comments
 (0)