subscribe to mut fds

This commit is contained in:
Pat Hickey
2021-04-26 16:06:56 -07:00
parent 867d2c9a35
commit a532d0f379
4 changed files with 39 additions and 11 deletions

View File

@@ -2,7 +2,7 @@ use crate::clocks::WasiMonotonicClock;
use crate::file::WasiFile; use crate::file::WasiFile;
use crate::Error; use crate::Error;
use cap_std::time::Instant; use cap_std::time::Instant;
use std::cell::Ref; use std::cell::RefMut;
pub mod subscription; pub mod subscription;
pub use cap_std::time::Duration; pub use cap_std::time::Duration;
@@ -52,11 +52,11 @@ impl<'a> Poll<'a> {
ud, ud,
)); ));
} }
pub fn subscribe_read(&mut self, file: Ref<'a, dyn WasiFile>, ud: Userdata) { pub fn subscribe_read(&mut self, file: RefMut<'a, dyn WasiFile>, ud: Userdata) {
self.subs self.subs
.push((Subscription::Read(RwSubscription::new(file)), ud)); .push((Subscription::Read(RwSubscription::new(file)), ud));
} }
pub fn subscribe_write(&mut self, file: Ref<'a, dyn WasiFile>, ud: Userdata) { pub fn subscribe_write(&mut self, file: RefMut<'a, dyn WasiFile>, ud: Userdata) {
self.subs self.subs
.push((Subscription::Write(RwSubscription::new(file)), ud)); .push((Subscription::Write(RwSubscription::new(file)), ud));
} }

View File

@@ -3,7 +3,7 @@ use crate::file::WasiFile;
use crate::Error; use crate::Error;
use bitflags::bitflags; use bitflags::bitflags;
use cap_std::time::{Duration, Instant}; use cap_std::time::{Duration, Instant};
use std::cell::{Cell, Ref}; use std::cell::{Cell, RefMut};
bitflags! { bitflags! {
pub struct RwEventFlags: u32 { pub struct RwEventFlags: u32 {
@@ -12,12 +12,12 @@ bitflags! {
} }
pub struct RwSubscription<'a> { pub struct RwSubscription<'a> {
pub file: Ref<'a, dyn WasiFile>, pub file: RefMut<'a, dyn WasiFile>,
status: Cell<Option<Result<(u64, RwEventFlags), Error>>>, status: Cell<Option<Result<(u64, RwEventFlags), Error>>>,
} }
impl<'a> RwSubscription<'a> { impl<'a> RwSubscription<'a> {
pub fn new(file: Ref<'a, dyn WasiFile>) -> Self { pub fn new(file: RefMut<'a, dyn WasiFile>) -> Self {
Self { Self {
file, file,
status: Cell::new(None), status: Cell::new(None),

View File

@@ -1,4 +1,4 @@
use crate::file::{FileCaps, FileEntryExt, TableFileExt}; use crate::file::{FileCaps, FileEntryExt, FileEntryMutExt, TableFileExt};
use crate::sched::{ use crate::sched::{
subscription::{RwEventFlags, SubscriptionResult}, subscription::{RwEventFlags, SubscriptionResult},
Poll, Poll,
@@ -7,6 +7,7 @@ use crate::snapshots::preview_1::types as snapshot1_types;
use crate::snapshots::preview_1::wasi_snapshot_preview1::WasiSnapshotPreview1 as Snapshot1; use crate::snapshots::preview_1::wasi_snapshot_preview1::WasiSnapshotPreview1 as Snapshot1;
use crate::{Error, ErrorExt, WasiCtx}; use crate::{Error, ErrorExt, WasiCtx};
use cap_std::time::Duration; use cap_std::time::Duration;
use std::collections::HashSet;
use std::convert::{TryFrom, TryInto}; use std::convert::{TryFrom, TryInto};
use std::io::{IoSlice, IoSliceMut}; use std::io::{IoSlice, IoSliceMut};
use std::ops::Deref; use std::ops::Deref;
@@ -778,6 +779,7 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
} }
let table = self.table(); let table = self.table();
let mut subscribed_fds = HashSet::new();
let mut poll = Poll::new(); let mut poll = Poll::new();
let subs = subs.as_array(nsubscriptions); let subs = subs.as_array(nsubscriptions);
@@ -816,15 +818,27 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
}, },
types::SubscriptionU::FdRead(readsub) => { types::SubscriptionU::FdRead(readsub) => {
let fd = readsub.file_descriptor; let fd = readsub.file_descriptor;
if subscribed_fds.contains(&fd) {
Err(Error::invalid_argument()
.context("Fd can be subscribed to at most once per poll_oneoff"))?;
} else {
subscribed_fds.insert(fd);
}
let file = table let file = table
.get_file(u32::from(fd))? .get_file_mut(u32::from(fd))?
.get_cap(FileCaps::POLL_READWRITE)?; .get_cap(FileCaps::POLL_READWRITE)?;
poll.subscribe_read(file, sub.userdata.into()); poll.subscribe_read(file, sub.userdata.into());
} }
types::SubscriptionU::FdWrite(writesub) => { types::SubscriptionU::FdWrite(writesub) => {
let fd = writesub.file_descriptor; let fd = writesub.file_descriptor;
if subscribed_fds.contains(&fd) {
Err(Error::invalid_argument()
.context("Fd can be subscribed to at most once per poll_oneoff"))?;
} else {
subscribed_fds.insert(fd);
}
let file = table let file = table
.get_file(u32::from(fd))? .get_file_mut(u32::from(fd))?
.get_cap(FileCaps::POLL_READWRITE)?; .get_cap(FileCaps::POLL_READWRITE)?;
poll.subscribe_write(file, sub.userdata.into()); poll.subscribe_write(file, sub.userdata.into());
} }

View File

@@ -13,6 +13,7 @@ use crate::{
use anyhow::Context; use anyhow::Context;
use cap_std::time::{Duration, SystemClock}; use cap_std::time::{Duration, SystemClock};
use std::cell::{Ref, RefMut}; use std::cell::{Ref, RefMut};
use std::collections::HashSet;
use std::convert::{TryFrom, TryInto}; use std::convert::{TryFrom, TryInto};
use std::io::{IoSlice, IoSliceMut}; use std::io::{IoSlice, IoSliceMut};
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
@@ -970,6 +971,7 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
} }
let table = self.table(); let table = self.table();
let mut subscribed_fds = HashSet::new();
let mut poll = Poll::new(); let mut poll = Poll::new();
let subs = subs.as_array(nsubscriptions); let subs = subs.as_array(nsubscriptions);
@@ -1008,15 +1010,27 @@ impl wasi_snapshot_preview1::WasiSnapshotPreview1 for WasiCtx {
}, },
types::SubscriptionU::FdRead(readsub) => { types::SubscriptionU::FdRead(readsub) => {
let fd = readsub.file_descriptor; let fd = readsub.file_descriptor;
if subscribed_fds.contains(&fd) {
return Err(Error::invalid_argument()
.context("Fd can be subscribed to at most once per poll_oneoff"));
} else {
subscribed_fds.insert(fd);
}
let file = table let file = table
.get_file(u32::from(fd))? .get_file_mut(u32::from(fd))?
.get_cap(FileCaps::POLL_READWRITE)?; .get_cap(FileCaps::POLL_READWRITE)?;
poll.subscribe_read(file, sub.userdata.into()); poll.subscribe_read(file, sub.userdata.into());
} }
types::SubscriptionU::FdWrite(writesub) => { types::SubscriptionU::FdWrite(writesub) => {
let fd = writesub.file_descriptor; let fd = writesub.file_descriptor;
if subscribed_fds.contains(&fd) {
return Err(Error::invalid_argument()
.context("Fd can be subscribed to at most once per poll_oneoff"));
} else {
subscribed_fds.insert(fd);
}
let file = table let file = table
.get_file(u32::from(fd))? .get_file_mut(u32::from(fd))?
.get_cap(FileCaps::POLL_READWRITE)?; .get_cap(FileCaps::POLL_READWRITE)?;
poll.subscribe_write(file, sub.userdata.into()); poll.subscribe_write(file, sub.userdata.into());
} }