3 // ignore-emscripten no processes
4 // ignore-sgx no processes
6 // [thir]compile-flags: -Zthir-unsafeck
8 #![feature(rustc_private)]
12 use std::process::{Command, Stdio};
14 use std::io::{self, Read, Write};
17 unsafe fn without_stdio<R, F: FnOnce() -> R>(f: F) -> R {
27 assert!(libc::close(0) >= 0);
28 assert!(libc::close(1) >= 0);
29 assert!(libc::close(2) >= 0);
33 assert!(libc::dup2(a, 0) >= 0);
34 assert!(libc::dup2(b, 1) >= 0);
35 assert!(libc::dup2(c, 2) >= 0);
41 fn assert_fd_is_valid(fd: libc::c_int) {
42 if unsafe { libc::fcntl(fd, libc::F_GETFD) == -1 } {
43 panic!("file descriptor {} is not valid: {}", fd, io::Error::last_os_error());
48 fn assert_fd_is_valid(_fd: libc::c_int) {}
51 unsafe fn without_stdio<R, F: FnOnce() -> R>(f: F) -> R {
53 type HANDLE = *mut u8;
56 const STD_INPUT_HANDLE: DWORD = -10i32 as DWORD;
57 const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD;
58 const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD;
59 const INVALID_HANDLE_VALUE: HANDLE = !0 as HANDLE;
62 fn GetStdHandle(which: DWORD) -> HANDLE;
63 fn SetStdHandle(which: DWORD, handle: HANDLE) -> BOOL;
67 let handle = GetStdHandle(id);
68 assert!(handle != INVALID_HANDLE_VALUE);
69 assert!(SetStdHandle(id, INVALID_HANDLE_VALUE) != 0);
73 let a = doit(STD_INPUT_HANDLE);
74 let b = doit(STD_OUTPUT_HANDLE);
75 let c = doit(STD_ERROR_HANDLE);
79 let doit = |id, handle| {
80 assert!(SetStdHandle(id, handle) != 0);
82 doit(STD_INPUT_HANDLE, a);
83 doit(STD_OUTPUT_HANDLE, b);
84 doit(STD_ERROR_HANDLE, c);
90 if env::args().len() > 1 {
91 // Writing to stdout & stderr should not panic.
93 assert!(io::stdout().write(b"test\n").is_ok());
94 assert!(io::stderr().write(b"test\n").is_ok());
96 // Stdin should be at EOF.
97 assert_eq!(io::stdin().read(&mut [0; 10]).unwrap(), 0);
99 // Standard file descriptors should be valid on UNIX:
100 assert_fd_is_valid(0);
101 assert_fd_is_valid(1);
102 assert_fd_is_valid(2);
106 // First, make sure reads/writes without stdio work if stdio itself is
108 let (a, b, c) = unsafe {
110 let a = io::stdout().write(b"test\n");
111 let b = io::stderr().write(b"test\n");
112 let c = io::stdin().read(&mut [0; 10]);
118 assert_eq!(a.unwrap(), 5);
119 assert_eq!(b.unwrap(), 5);
120 assert_eq!(c.unwrap(), 0);
122 // Second, spawn a child and do some work with "null" descriptors to make
124 let me = env::current_exe().unwrap();
125 let status = Command::new(&me)
127 .stdin(Stdio::null())
128 .stdout(Stdio::null())
129 .stderr(Stdio::null())
131 assert!(status.success(), "{} isn't a success", status);
133 // Finally, close everything then spawn a child to make sure everything is
135 let status = unsafe {
136 without_stdio(|| Command::new(&me).arg("next").status())
138 assert!(status.success(), "{} isn't a success", status);