Path: blob/main/crates/wasi-common/src/sync/sched/unix.rs
1693 views
use crate::sched::subscription::{RwEventFlags, Subscription};1use crate::{Error, ErrorExt, sched::Poll};2use cap_std::time::Duration;3use rustix::event::{PollFd, PollFlags};45pub async fn poll_oneoff<'a>(poll: &mut Poll<'a>) -> Result<(), Error> {6if poll.is_empty() {7return Ok(());8}9let mut pollfds = Vec::new();10for s in poll.rw_subscriptions() {11match s {12Subscription::Read(f) => {13let fd = f14.file15.pollable()16.ok_or(Error::invalid_argument().context("file is not pollable"))?;17pollfds.push(PollFd::from_borrowed_fd(fd, PollFlags::IN));18}1920Subscription::Write(f) => {21let fd = f22.file23.pollable()24.ok_or(Error::invalid_argument().context("file is not pollable"))?;25pollfds.push(PollFd::from_borrowed_fd(fd, PollFlags::OUT));26}27Subscription::MonotonicClock { .. } => unreachable!(),28}29}3031let ready = loop {32let poll_timeout = if let Some(t) = poll.earliest_clock_deadline() {33let duration = t.duration_until().unwrap_or(Duration::from_secs(0));34Some(35duration36.try_into()37.map_err(|_| Error::overflow().context("poll timeout"))?,38)39} else {40None41};42tracing::debug!(43poll_timeout = tracing::field::debug(poll_timeout),44poll_fds = tracing::field::debug(&pollfds),45"poll"46);47match rustix::event::poll(&mut pollfds, poll_timeout.as_ref()) {48Ok(ready) => break ready,49Err(rustix::io::Errno::INTR) => continue,50Err(err) => return Err(std::io::Error::from(err).into()),51}52};53if ready > 0 {54for (rwsub, pollfd) in poll.rw_subscriptions().zip(pollfds.into_iter()) {55let revents = pollfd.revents();56let (nbytes, rwsub) = match rwsub {57Subscription::Read(sub) => {58let ready = sub.file.num_ready_bytes()?;59(std::cmp::max(ready, 1), sub)60}61Subscription::Write(sub) => (0, sub),62_ => unreachable!(),63};64if revents.contains(PollFlags::NVAL) {65rwsub.error(Error::badf());66} else if revents.contains(PollFlags::ERR) {67rwsub.error(Error::io());68} else if revents.contains(PollFlags::HUP) {69rwsub.complete(nbytes, RwEventFlags::HANGUP);70} else {71rwsub.complete(nbytes, RwEventFlags::empty());72};73}74} else {75poll.earliest_clock_deadline()76.expect("timed out")77.result()78.expect("timer deadline is past")79.unwrap()80}81Ok(())82}838485