1 // run-pass
2 // ignore-emscripten no processes
3 // ignore-sgx no processes
4 
5 use std::env;
6 use std::io::prelude::*;
7 use std::process::Command;
8 use std::thread;
9 
10 const THREADS: usize = 20;
11 const WRITES: usize = 100;
12 const WRITE_SIZE: usize = 1024 * 32;
13 
main()14 fn main() {
15     let args = env::args().collect::<Vec<_>>();
16     if args.len() == 1 {
17         parent();
18     } else {
19         child();
20     }
21 }
22 
parent()23 fn parent() {
24     let me = env::current_exe().unwrap();
25     let mut cmd = Command::new(me);
26     cmd.arg("run-the-test");
27     let output = cmd.output().unwrap();
28     assert!(output.status.success());
29     assert_eq!(output.stderr.len(), 0);
30     assert_eq!(output.stdout.len(), WRITES * THREADS * WRITE_SIZE);
31     for byte in output.stdout.iter() {
32         assert_eq!(*byte, b'a');
33     }
34 }
35 
child()36 fn child() {
37     let threads = (0..THREADS).map(|_| {
38         thread::spawn(|| {
39             let buf = [b'a'; WRITE_SIZE];
40             for _ in 0..WRITES {
41                 write_all(&buf);
42             }
43         })
44     }).collect::<Vec<_>>();
45 
46     for thread in threads {
47         thread.join().unwrap();
48     }
49 }
50 
51 #[cfg(unix)]
write_all(buf: &[u8])52 fn write_all(buf: &[u8]) {
53     use std::fs::File;
54     use std::mem;
55     use std::os::unix::prelude::*;
56 
57     let mut file = unsafe { File::from_raw_fd(1) };
58     let res = file.write_all(buf);
59     mem::forget(file);
60     res.unwrap();
61 }
62 
63 #[cfg(windows)]
write_all(buf: &[u8])64 fn write_all(buf: &[u8]) {
65     use std::fs::File;
66     use std::mem;
67     use std::os::windows::raw::*;
68     use std::os::windows::prelude::*;
69 
70     const STD_OUTPUT_HANDLE: u32 = (-11i32) as u32;
71 
72     extern "system" {
73         fn GetStdHandle(handle: u32) -> HANDLE;
74     }
75 
76     let mut file = unsafe {
77         let handle = GetStdHandle(STD_OUTPUT_HANDLE);
78         assert!(!handle.is_null());
79         File::from_raw_handle(handle)
80     };
81     let res = file.write_all(buf);
82     mem::forget(file);
83     res.unwrap();
84 }
85