fix(wasi): enable all WasiFiles to be pollable (#3913)

Currently, the use of the downcast method means that you have to use one
of the hard-coded types. But Enarx needs to define its own `WasiFile`
implementations. This works fine, except the resulting files cannot be
used in poll because they aren't part of the hard-coded list.

Replace this with an accessor method for the pollable type in
`WasiFile`. Because we provide a default implementation of the method
and manually implement it on all the hard-coded types, this is backwards
compatible.

Signed-off-by: Nathaniel McCallum <nathaniel@profian.com>
This commit is contained in:
Nathaniel McCallum
2022-03-10 13:09:06 -05:00
committed by GitHub
parent 13b9396931
commit 0df4e961c0
10 changed files with 84 additions and 150 deletions

View File

@@ -94,6 +94,15 @@ macro_rules! wasi_file_impl {
fn as_any(&self) -> &dyn Any {
self
}
#[cfg(unix)]
fn pollable(&self) -> Option<rustix::fd::BorrowedFd> {
Some(self.0.as_fd())
}
#[cfg(windows)]
fn pollable(&self) -> Option<io_extras::os::windows::RawHandleOrSocket> {
Some(self.0.as_raw_handle_or_socket())
}
async fn datasync(&mut self) -> Result<(), Error> {
block_on_dummy_executor(|| self.0.datasync())
}

View File

@@ -1,5 +1,4 @@
use crate::block_on_dummy_executor;
use io_extras::os::windows::{AsRawHandleOrSocket, RawHandleOrSocket};
use wasi_cap_std_sync::sched::windows::poll_oneoff_;
use wasi_common::{file::WasiFile, sched::Poll, Error};
@@ -8,52 +7,9 @@ pub async fn poll_oneoff<'a>(poll: &mut Poll<'a>) -> Result<(), Error> {
// we use the blocking poll_oneoff implementation from the wasi-cap-std-crate.
// We provide a function specific to this crate's WasiFile types for downcasting
// to a RawHandle.
block_on_dummy_executor(move || poll_oneoff_(poll, wasi_file_is_stdin, wasi_file_raw_handle))
block_on_dummy_executor(move || poll_oneoff_(poll, wasi_file_is_stdin))
}
pub fn wasi_file_is_stdin(f: &dyn WasiFile) -> bool {
f.as_any().is::<crate::stdio::Stdin>()
}
fn wasi_file_raw_handle(f: &dyn WasiFile) -> Option<RawHandleOrSocket> {
let a = f.as_any();
if a.is::<crate::file::File>() {
Some(
a.downcast_ref::<crate::file::File>()
.unwrap()
.as_raw_handle_or_socket(),
)
} else if a.is::<crate::net::TcpListener>() {
Some(
a.downcast_ref::<crate::net::TcpListener>()
.unwrap()
.as_raw_handle_or_socket(),
)
} else if a.is::<crate::net::TcpStream>() {
Some(
a.downcast_ref::<crate::net::TcpStream>()
.unwrap()
.as_raw_handle_or_socket(),
)
} else if a.is::<crate::stdio::Stdin>() {
Some(
a.downcast_ref::<crate::stdio::Stdin>()
.unwrap()
.as_raw_handle_or_socket(),
)
} else if a.is::<crate::stdio::Stdout>() {
Some(
a.downcast_ref::<crate::stdio::Stdout>()
.unwrap()
.as_raw_handle_or_socket(),
)
} else if a.is::<crate::stdio::Stderr>() {
Some(
a.downcast_ref::<crate::stdio::Stderr>()
.unwrap()
.as_raw_handle_or_socket(),
)
} else {
None
}
}