[wasi-common]: clean up error handling (#1253)
* Introduce WasiCtxBuilderError error type `WasiCtxBuilderError` is the `wasi-common` client-facing error type which is exclusively thrown when building a new `WasiCtx` instance. As such, building such an instance should not require the client to understand different WASI errno values as was assumed until now. This commit is a first step at streamlining error handling in `wasi-common` and makes way for the `wiggle` crate. When adding the `WasiCtxBuilderError`, I've had to do two things of notable importance: 1. I've removed a couple of `ok_or` calls in `WasiCtxBuilder::build` and replaced them with `unwrap`s, following the same pattern in different builder methods above. This is fine since we _always_ operate on non-empty `Option`s in `WasiCtxBuilder` thus `unwrap`ing will never fail. On the other hand, this might be a good opportunity to rethink the structure of our builder, and how we good remove the said `Option`s especially since we always populate them with empty containers to begin with. I understand this is to make chaining of builder methods easier which take and return `&mut self` and the same applies to `WasiCtxBuilder::build(&mut self)` method, but perhaps it would more cleanly signal the intentions if we simply moved `WasiCtxBuilder` instance around. Food for thought! 2. Methods specific to determining rights of passed around `std::fs::File` objects when populating `WasiCtx` `FdEntry` entities now return `io::Error` directly so that we can reuse them in `WasiCtxBuilder` methods (returning `WasiCtxBuilderError` error type), and in syscalls (returning WASI errno). * Return WasiError directly in syscalls Also, removes `error::Error` type altogether. Now, `io::Error` and related are automatically converted to their corresponding WASI errno value encapsulated as `WasiError`. While here, it made sense to me to move `WasiError` to `wasi` module which will align itself well with the upcoming changes introduced by `wiggle`. To different standard `Result` from WASI specific, I've created a helper alias `WasiResult` also residing in `wasi` module. * Update wig * Add from ffi::NulError and pass context to NotADirectory * Add dummy commit to test CI
This commit is contained in:
@@ -1,22 +1,24 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(unused_unsafe)]
|
||||
use crate::hostcalls_impl::{ClockEventData, FdEventData};
|
||||
use crate::{wasi, Error, Result};
|
||||
use crate::wasi::{self, WasiError, WasiResult};
|
||||
use std::io;
|
||||
use yanix::clock::{clock_getres, clock_gettime, ClockId};
|
||||
|
||||
fn wasi_clock_id_to_unix(clock_id: wasi::__wasi_clockid_t) -> Result<ClockId> {
|
||||
fn wasi_clock_id_to_unix(clock_id: wasi::__wasi_clockid_t) -> WasiResult<ClockId> {
|
||||
// convert the supported clocks to libc types, or return EINVAL
|
||||
match clock_id {
|
||||
wasi::__WASI_CLOCKID_REALTIME => Ok(ClockId::Realtime),
|
||||
wasi::__WASI_CLOCKID_MONOTONIC => Ok(ClockId::Monotonic),
|
||||
wasi::__WASI_CLOCKID_PROCESS_CPUTIME_ID => Ok(ClockId::ProcessCPUTime),
|
||||
wasi::__WASI_CLOCKID_THREAD_CPUTIME_ID => Ok(ClockId::ThreadCPUTime),
|
||||
_ => Err(Error::EINVAL),
|
||||
_ => Err(WasiError::EINVAL),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn clock_res_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::__wasi_timestamp_t> {
|
||||
pub(crate) fn clock_res_get(
|
||||
clock_id: wasi::__wasi_clockid_t,
|
||||
) -> WasiResult<wasi::__wasi_timestamp_t> {
|
||||
let clock_id = wasi_clock_id_to_unix(clock_id)?;
|
||||
let timespec = clock_getres(clock_id)?;
|
||||
|
||||
@@ -26,18 +28,20 @@ pub(crate) fn clock_res_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::__
|
||||
(timespec.tv_sec as wasi::__wasi_timestamp_t)
|
||||
.checked_mul(1_000_000_000)
|
||||
.and_then(|sec_ns| sec_ns.checked_add(timespec.tv_nsec as wasi::__wasi_timestamp_t))
|
||||
.map_or(Err(Error::EOVERFLOW), |resolution| {
|
||||
.map_or(Err(WasiError::EOVERFLOW), |resolution| {
|
||||
// a supported clock can never return zero; this case will probably never get hit, but
|
||||
// make sure we follow the spec
|
||||
if resolution == 0 {
|
||||
Err(Error::EINVAL)
|
||||
Err(WasiError::EINVAL)
|
||||
} else {
|
||||
Ok(resolution)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn clock_time_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::__wasi_timestamp_t> {
|
||||
pub(crate) fn clock_time_get(
|
||||
clock_id: wasi::__wasi_clockid_t,
|
||||
) -> WasiResult<wasi::__wasi_timestamp_t> {
|
||||
let clock_id = wasi_clock_id_to_unix(clock_id)?;
|
||||
let timespec = clock_gettime(clock_id)?;
|
||||
|
||||
@@ -46,14 +50,14 @@ pub(crate) fn clock_time_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::_
|
||||
(timespec.tv_sec as wasi::__wasi_timestamp_t)
|
||||
.checked_mul(1_000_000_000)
|
||||
.and_then(|sec_ns| sec_ns.checked_add(timespec.tv_nsec as wasi::__wasi_timestamp_t))
|
||||
.map_or(Err(Error::EOVERFLOW), Ok)
|
||||
.map_or(Err(WasiError::EOVERFLOW), Ok)
|
||||
}
|
||||
|
||||
pub(crate) fn poll_oneoff(
|
||||
timeout: Option<ClockEventData>,
|
||||
fd_events: Vec<FdEventData>,
|
||||
events: &mut Vec<wasi::__wasi_event_t>,
|
||||
) -> Result<()> {
|
||||
) -> WasiResult<()> {
|
||||
use std::{convert::TryInto, os::unix::prelude::AsRawFd};
|
||||
use yanix::poll::{poll, PollFd, PollFlags};
|
||||
|
||||
@@ -122,12 +126,12 @@ fn poll_oneoff_handle_timeout_event(
|
||||
fn poll_oneoff_handle_fd_event<'a>(
|
||||
ready_events: impl Iterator<Item = (FdEventData<'a>, yanix::poll::PollFd)>,
|
||||
events: &mut Vec<wasi::__wasi_event_t>,
|
||||
) -> Result<()> {
|
||||
) -> WasiResult<()> {
|
||||
use crate::fdentry::Descriptor;
|
||||
use std::{convert::TryInto, os::unix::prelude::AsRawFd};
|
||||
use yanix::{file::fionread, poll::PollFlags};
|
||||
|
||||
fn query_nbytes(fd: &Descriptor) -> Result<u64> {
|
||||
fn query_nbytes(fd: &Descriptor) -> WasiResult<u64> {
|
||||
// fionread may overflow for large files, so use another way for regular files.
|
||||
if let Descriptor::OsHandle(os_handle) = fd {
|
||||
let meta = os_handle.metadata()?;
|
||||
|
||||
Reference in New Issue
Block a user