Merge pull request #2550 from bytecodealliance/pch/wiggle_trapping

wiggle: introduce Trap enum
This commit is contained in:
Nick Fitzgerald
2021-01-07 16:23:21 -08:00
committed by GitHub
26 changed files with 190 additions and 145 deletions

View File

@@ -17,6 +17,10 @@ pub enum Error {
#[error("GetRandom: {0}")]
GetRandom(#[from] getrandom::Error),
/// Some corners of the WASI standard are unsupported.
#[error("Unsupported: {0}")]
Unsupported(&'static str),
/// The host OS may return an io error that doesn't match one of the
/// wasi errno variants we expect. We do not expose the details of this
/// error to the user.

View File

@@ -714,14 +714,17 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
Ok(nevents)
}
fn proc_exit(&self, _rval: types::Exitcode) -> std::result::Result<(), ()> {
// proc_exit is special in that it's expected to unwind the stack, which
// typically requires runtime-specific logic.
unimplemented!("runtimes are expected to override this implementation")
fn proc_exit(&self, status: types::Exitcode) -> wiggle::Trap {
// Check that the status is within WASI's range.
if status < 126 {
wiggle::Trap::I32Exit(status as i32)
} else {
wiggle::Trap::String("exit with invalid exit status outside of [0..126)".to_owned())
}
}
fn proc_raise(&self, _sig: types::Signal) -> Result<()> {
unimplemented!("proc_raise")
Err(Error::Unsupported("proc_raise"))
}
fn sched_yield(&self) -> Result<()> {
@@ -741,7 +744,7 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
_ri_data: &types::IovecArray<'_>,
_ri_flags: types::Riflags,
) -> Result<(types::Size, types::Roflags)> {
unimplemented!("sock_recv")
Err(Error::Unsupported("sock_recv"))
}
fn sock_send(
@@ -750,11 +753,11 @@ impl<'a> WasiSnapshotPreview1 for WasiCtx {
_si_data: &types::CiovecArray<'_>,
_si_flags: types::Siflags,
) -> Result<types::Size> {
unimplemented!("sock_send")
Err(Error::Unsupported("sock_send"))
}
fn sock_shutdown(&self, _fd: types::Fd, _how: types::Sdflags) -> Result<()> {
unimplemented!("sock_shutdown")
Err(Error::Unsupported("sock_shutdown"))
}
}
@@ -801,7 +804,7 @@ impl WasiCtx {
Err(error) => {
events.push(types::Event {
userdata: subscription.userdata,
error: error.into(),
error: error.try_into().expect("non-trapping error"),
type_: types::Eventtype::FdRead,
fd_readwrite: types::EventFdReadwrite {
nbytes: 0,
@@ -827,7 +830,7 @@ impl WasiCtx {
Err(error) => {
events.push(types::Event {
userdata: subscription.userdata,
error: error.into(),
error: error.try_into().expect("non-trapping error"),
type_: types::Eventtype::FdWrite,
fd_readwrite: types::EventFdReadwrite {
nbytes: 0,

View File

@@ -23,15 +23,16 @@ impl types::GuestErrorConversion for WasiCtx {
}
impl types::UserErrorConversion for WasiCtx {
fn errno_from_error(&self, e: Error) -> Result<Errno, String> {
fn errno_from_error(&self, e: Error) -> Result<Errno, wiggle::Trap> {
tracing::debug!("Error: {:?}", e);
Ok(e.into())
e.try_into()
}
}
impl From<Error> for Errno {
fn from(e: Error) -> Errno {
types_new::Errno::from(e).into()
impl TryFrom<Error> for Errno {
type Error = wiggle::Trap;
fn try_from(e: Error) -> Result<Errno, wiggle::Trap> {
Ok(types_new::Errno::try_from(e)?.into())
}
}
@@ -346,7 +347,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
Ok(nevents)
}
fn proc_exit(&self, rval: Exitcode) -> Result<(), ()> {
fn proc_exit(&self, rval: Exitcode) -> wiggle::Trap {
WasiSnapshotPreview1::proc_exit(self, rval)
}

View File

@@ -117,7 +117,7 @@ fn handle_fd_event(
let output_event = if revents.contains(PollFlags::POLLNVAL) {
Event {
userdata: fd_event.userdata,
error: Error::Badf.into(),
error: Error::Badf.try_into().unwrap(),
type_: fd_event.r#type,
fd_readwrite: EventFdReadwrite {
nbytes: 0,
@@ -127,7 +127,7 @@ fn handle_fd_event(
} else if revents.contains(PollFlags::POLLERR) {
Event {
userdata: fd_event.userdata,
error: Error::Io.into(),
error: Error::Io.try_into().unwrap(),
type_: fd_event.r#type,
fd_readwrite: EventFdReadwrite {
nbytes: 0,

View File

@@ -9,7 +9,7 @@ use crate::sys::stdio::{Stderr, Stdin, Stdout};
use crate::sys::AsFile;
use crate::{Error, Result};
use lazy_static::lazy_static;
use std::convert::TryInto;
use std::convert::{TryFrom, TryInto};
use std::sync::mpsc::{self, Receiver, RecvTimeoutError, Sender, TryRecvError};
use std::sync::Mutex;
use std::thread;
@@ -81,7 +81,9 @@ impl StdinPoll {
// Linux returns `POLLIN` in both cases, and we imitate this behavior.
let resp = match std::io::stdin().lock().fill_buf() {
Ok(_) => PollState::Ready,
Err(e) => PollState::Error(Errno::from(Error::from(e))),
Err(e) => {
PollState::Error(Errno::try_from(Error::from(e)).expect("non-trapping error"))
}
};
// Notify the requestor about data in stdin. They may have already timed out,
@@ -158,7 +160,9 @@ fn handle_rw_event(event: FdEventData, out_events: &mut Vec<Event>) {
.as_file()
.and_then(|f| f.metadata())
.map(|m| m.len())
.map_err(|ioerror| Errno::from(Error::from(ioerror)))
.map_err(|ioerror| {
Errno::try_from(Error::from(ioerror)).expect("non-trapping error")
})
} else {
// The spec is unclear what nbytes should actually be for __WASI_EVENTTYPE_FD_WRITE and
// the implementation on Unix just returns 0 here, so it's probably fine

View File

@@ -1,4 +1,5 @@
use crate::{Error, WasiCtx};
use std::convert::{TryFrom, TryInto};
use tracing::debug;
wiggle::from_witx!({
@@ -23,47 +24,51 @@ impl types::GuestErrorConversion for WasiCtx {
}
impl types::UserErrorConversion for WasiCtx {
fn errno_from_error(&self, e: Error) -> Result<Errno, String> {
fn errno_from_error(&self, e: Error) -> Result<Errno, wiggle::Trap> {
debug!("Error: {:?}", e);
Ok(e.into())
e.try_into()
}
}
impl From<Error> for Errno {
fn from(e: Error) -> Errno {
impl TryFrom<Error> for Errno {
type Error = wiggle::Trap;
fn try_from(e: Error) -> Result<Errno, wiggle::Trap> {
match e {
Error::Guest(e) => e.into(),
Error::TryFromInt(_) => Errno::Overflow,
Error::Utf8(_) => Errno::Ilseq,
Error::UnexpectedIo(_) => Errno::Io,
Error::GetRandom(_) => Errno::Io,
Error::TooBig => Errno::TooBig,
Error::Acces => Errno::Acces,
Error::Badf => Errno::Badf,
Error::Busy => Errno::Busy,
Error::Exist => Errno::Exist,
Error::Fault => Errno::Fault,
Error::Fbig => Errno::Fbig,
Error::Ilseq => Errno::Ilseq,
Error::Inval => Errno::Inval,
Error::Io => Errno::Io,
Error::Isdir => Errno::Isdir,
Error::Loop => Errno::Loop,
Error::Mfile => Errno::Mfile,
Error::Mlink => Errno::Mlink,
Error::Nametoolong => Errno::Nametoolong,
Error::Nfile => Errno::Nfile,
Error::Noent => Errno::Noent,
Error::Nomem => Errno::Nomem,
Error::Nospc => Errno::Nospc,
Error::Notdir => Errno::Notdir,
Error::Notempty => Errno::Notempty,
Error::Notsup => Errno::Notsup,
Error::Overflow => Errno::Overflow,
Error::Pipe => Errno::Pipe,
Error::Perm => Errno::Perm,
Error::Spipe => Errno::Spipe,
Error::Notcapable => Errno::Notcapable,
Error::Guest(e) => Ok(e.into()),
Error::TryFromInt(_) => Ok(Errno::Overflow),
Error::Utf8(_) => Ok(Errno::Ilseq),
Error::UnexpectedIo(_) => Ok(Errno::Io),
Error::GetRandom(_) => Ok(Errno::Io),
Error::TooBig => Ok(Errno::TooBig),
Error::Acces => Ok(Errno::Acces),
Error::Badf => Ok(Errno::Badf),
Error::Busy => Ok(Errno::Busy),
Error::Exist => Ok(Errno::Exist),
Error::Fault => Ok(Errno::Fault),
Error::Fbig => Ok(Errno::Fbig),
Error::Ilseq => Ok(Errno::Ilseq),
Error::Inval => Ok(Errno::Inval),
Error::Io => Ok(Errno::Io),
Error::Isdir => Ok(Errno::Isdir),
Error::Loop => Ok(Errno::Loop),
Error::Mfile => Ok(Errno::Mfile),
Error::Mlink => Ok(Errno::Mlink),
Error::Nametoolong => Ok(Errno::Nametoolong),
Error::Nfile => Ok(Errno::Nfile),
Error::Noent => Ok(Errno::Noent),
Error::Nomem => Ok(Errno::Nomem),
Error::Nospc => Ok(Errno::Nospc),
Error::Notdir => Ok(Errno::Notdir),
Error::Notempty => Ok(Errno::Notempty),
Error::Notsup => Ok(Errno::Notsup),
Error::Overflow => Ok(Errno::Overflow),
Error::Pipe => Ok(Errno::Pipe),
Error::Perm => Ok(Errno::Perm),
Error::Spipe => Ok(Errno::Spipe),
Error::Notcapable => Ok(Errno::Notcapable),
Error::Unsupported(feature) => {
Err(wiggle::Trap::String(format!("unsupported: {}", feature)))
}
}
}
}
@@ -80,8 +85,8 @@ impl From<wiggle::GuestError> for Errno {
PtrBorrowed { .. } => Self::Fault,
InvalidUtf8 { .. } => Self::Ilseq,
TryFromIntError { .. } => Self::Overflow,
InFunc { .. } => Self::Inval,
InDataField { .. } => Self::Inval,
InFunc { err, .. } => Errno::from(*err),
InDataField { err, .. } => Errno::from(*err),
SliceLengthsDiffer { .. } => Self::Fault,
BorrowCheckerOutOfHandles { .. } => Self::Fault,
}