diff --git a/lib/wasi-tests/wasitests/poll_oneoff.out b/lib/wasi-tests/wasitests/poll_oneoff.out index ea8f6542388..055f45f4708 100644 --- a/lib/wasi-tests/wasitests/poll_oneoff.out +++ b/lib/wasi-tests/wasitests/poll_oneoff.out @@ -1,2 +1,5 @@ __wasi_event_t { userdata: 1193046, error: 0, type_: 1, u: __wasi_event_u { __wasi_event_fd_readwrite_t { nbytes: 2259, flags: 0 } } } [__wasi_event_t { userdata: 1193046, error: 0, type_: 1, u: __wasi_event_u { __wasi_event_fd_readwrite_t { nbytes: 2259, flags: 0 } } }, __wasi_event_t { userdata: 1193046, error: 0, type_: 2, u: __wasi_event_u { __wasi_event_fd_readwrite_t { nbytes: 1234, flags: 0 } } }] +Stdin: OK +Stdout: OK +Stderr: OK diff --git a/lib/wasi-tests/wasitests/poll_oneoff.rs b/lib/wasi-tests/wasitests/poll_oneoff.rs index 255f5e91ed3..6170e5fb576 100644 --- a/lib/wasi-tests/wasitests/poll_oneoff.rs +++ b/lib/wasi-tests/wasitests/poll_oneoff.rs @@ -171,11 +171,46 @@ fn main() { poll(fds.as_slice(), &[true, false], &[false, true]).expect("subsequent polls"); } println!("{:?}", result); + + /// stdin, stdout, stderr checking + let fds = vec![std::io::stdin().as_raw_fd()]; + print!("Stdin: "); + println!( + "{}", + if poll(fds.as_slice(), &[true], &[false]).is_ok() { + "OK" + } else { + "ERROR" + } + ); + let fds = vec![std::io::stdout().as_raw_fd()]; + print!("Stdout: "); + println!( + "{}", + if poll(fds.as_slice(), &[false], &[true]).is_ok() { + "OK" + } else { + "ERROR" + } + ); + let fds = vec![std::io::stderr().as_raw_fd()]; + print!("Stderr: "); + println!( + "{}", + if poll(fds.as_slice(), &[false], &[true]).is_ok() { + "OK" + } else { + "ERROR" + } + ); } #[cfg(not(target_os = "wasi"))] { println!("{}", "__wasi_event_t { userdata: 1193046, error: 0, type_: 1, u: __wasi_event_u { __wasi_event_fd_readwrite_t { nbytes: 2259, flags: 0 } } }"); println!("{}", "[__wasi_event_t { userdata: 1193046, error: 0, type_: 1, u: __wasi_event_u { __wasi_event_fd_readwrite_t { nbytes: 2259, flags: 0 } } }, __wasi_event_t { userdata: 1193046, error: 0, type_: 2, u: __wasi_event_u { __wasi_event_fd_readwrite_t { nbytes: 1234, flags: 0 } } }]"); + println!("Stdin: OK"); + println!("Stdout: OK"); + println!("Stderr: OK"); } } diff --git a/lib/wasi-tests/wasitests/poll_oneoff.wasm b/lib/wasi-tests/wasitests/poll_oneoff.wasm index c74bcb072f2..950345d0bde 100755 Binary files a/lib/wasi-tests/wasitests/poll_oneoff.wasm and b/lib/wasi-tests/wasitests/poll_oneoff.wasm differ diff --git a/lib/wasi/src/state/types.rs b/lib/wasi/src/state/types.rs index 09dfe424739..85b84a811b0 100644 --- a/lib/wasi/src/state/types.rs +++ b/lib/wasi/src/state/types.rs @@ -452,26 +452,11 @@ impl WasiFile for HostFile { std::fs::rename(&self.host_path, new_name).map_err(Into::into) } - #[cfg(unix)] - fn bytes_available(&self) -> Result { - use std::os::unix::io::AsRawFd; - let host_fd = self.inner.as_raw_fd(); - - let mut bytes_found = 0 as libc::c_int; - let result = unsafe { libc::ioctl(host_fd, libc::FIONREAD, &mut bytes_found) }; - - match result { - // success - 0 => Ok(bytes_found.try_into().unwrap_or(0)), - libc::EBADF => Err(WasiFsError::InvalidFd), - libc::EFAULT => Err(WasiFsError::InvalidData), - libc::EINVAL => Err(WasiFsError::InvalidInput), - _ => Err(WasiFsError::IOError), - } - } - #[cfg(not(unix))] fn bytes_available(&self) -> Result { - unimplemented!("HostFile::bytes_available in WasiFile is not implemented for non-Unix-like targets yet"); + // unwrap is safe because of get_raw_fd implementation + let host_fd = self.get_raw_fd().unwrap(); + + host_file_bytes_available(host_fd) } #[cfg(unix)] @@ -514,6 +499,26 @@ impl From for WasiFsError { } } +#[cfg(unix)] +fn host_file_bytes_available(host_fd: i32) -> Result { + let mut bytes_found = 0 as libc::c_int; + let result = unsafe { libc::ioctl(host_fd, libc::FIONREAD, &mut bytes_found) }; + + match result { + // success + 0 => Ok(bytes_found.try_into().unwrap_or(0)), + libc::EBADF => Err(WasiFsError::InvalidFd), + libc::EFAULT => Err(WasiFsError::InvalidData), + libc::EINVAL => Err(WasiFsError::InvalidInput), + _ => Err(WasiFsError::IOError), + } +} + +#[cfg(not(unix))] +fn host_file_bytes_available(_raw_fd: i32) -> Result { + unimplemented!("host_file_bytes_available not yet implemented for non-Unix-like targets. This probably means the program tried to use wasi::poll_oneoff") +} + #[derive(Debug)] pub struct Stdout(pub std::io::Stdout); impl Read for Stdout { @@ -579,6 +584,13 @@ impl WasiFile for Stdout { 0 } + fn bytes_available(&self) -> Result { + // unwrap is safe because of get_raw_fd implementation + let host_fd = self.get_raw_fd().unwrap(); + + host_file_bytes_available(host_fd) + } + #[cfg(unix)] fn get_raw_fd(&self) -> Option { use std::os::unix::io::AsRawFd; @@ -658,6 +670,13 @@ impl WasiFile for Stderr { 0 } + fn bytes_available(&self) -> Result { + // unwrap is safe because of get_raw_fd implementation + let host_fd = self.get_raw_fd().unwrap(); + + host_file_bytes_available(host_fd) + } + #[cfg(unix)] fn get_raw_fd(&self) -> Option { use std::os::unix::io::AsRawFd; @@ -737,28 +756,11 @@ impl WasiFile for Stdin { 0 } - #[cfg(unix)] fn bytes_available(&self) -> Result { - use std::os::unix::io::AsRawFd; - let host_fd = self.0.as_raw_fd(); - - let mut bytes_found = 0 as libc::c_int; - let result = unsafe { libc::ioctl(host_fd, libc::FIONREAD, &mut bytes_found) }; - - match result { - // success - 0 => Ok(bytes_found.try_into().unwrap_or(0)), - libc::EBADF => Err(WasiFsError::InvalidFd), - libc::EFAULT => Err(WasiFsError::InvalidData), - libc::EINVAL => Err(WasiFsError::InvalidInput), - _ => Err(WasiFsError::IOError), - } - } - #[cfg(not(unix))] - fn bytes_available(&self) -> Result { - unimplemented!( - "Stdin::bytes_available in WasiFile is not implemented for non-Unix-like targets yet" - ); + // unwrap is safe because of get_raw_fd implementation + let host_fd = self.get_raw_fd().unwrap(); + + host_file_bytes_available(host_fd) } #[cfg(unix)] diff --git a/lib/wasi/src/syscalls/mod.rs b/lib/wasi/src/syscalls/mod.rs index d1c44ca2797..1ac27c89be2 100644 --- a/lib/wasi/src/syscalls/mod.rs +++ b/lib/wasi/src/syscalls/mod.rs @@ -2267,17 +2267,28 @@ pub fn poll_oneoff( let fd = match s.event_type { EventType::Read(__wasi_subscription_fs_readwrite_t { fd }) => { - let fd_entry = wasi_try!(state.fs.get_fd(fd)); - if !has_rights(fd_entry.rights, __WASI_RIGHT_FD_READ) { - return __WASI_EACCES; + match fd { + __WASI_STDIN_FILENO | __WASI_STDOUT_FILENO | __WASI_STDERR_FILENO => (), + _ => { + let fd_entry = wasi_try!(state.fs.get_fd(fd)); + if !has_rights(fd_entry.rights, __WASI_RIGHT_FD_READ) { + return __WASI_EACCES; + } + } } in_events.push(peb.add(PollEvent::PollIn).build()); Some(fd) } EventType::Write(__wasi_subscription_fs_readwrite_t { fd }) => { - let fd_entry = wasi_try!(state.fs.get_fd(fd)); - if !has_rights(fd_entry.rights, __WASI_RIGHT_FD_WRITE) { - return __WASI_EACCES; + match fd { + __WASI_STDIN_FILENO | __WASI_STDOUT_FILENO | __WASI_STDERR_FILENO => (), + _ => { + let fd_entry = wasi_try!(state.fs.get_fd(fd)); + + if !has_rights(fd_entry.rights, __WASI_RIGHT_FD_WRITE) { + return __WASI_EACCES; + } + } } in_events.push(peb.add(PollEvent::PollOut).build()); Some(fd)