jump through enough hoops for the poll lifetime to work out

you program rust for a few years and you think you're done tearing your
hair out over lifetimes, well, you'll find yourself wrong
This commit is contained in:
Pat Hickey
2021-04-29 16:44:45 -07:00
parent ab4f5bb674
commit b7efcbe80f
8 changed files with 99 additions and 87 deletions

View File

@@ -1,12 +1,14 @@
use crate::file::{FileCaps, FileEntryExt, TableFileExt};
use crate::file::{FileCaps, FileEntryExt, FileEntryMutExt, TableFileExt, WasiFile};
use crate::sched::{
subscription::{RwEventFlags, SubscriptionResult},
Poll,
Poll, Userdata,
};
use crate::snapshots::preview_1::types as snapshot1_types;
use crate::snapshots::preview_1::wasi_snapshot_preview1::WasiSnapshotPreview1 as Snapshot1;
use crate::{Error, ErrorExt, WasiCtx};
use cap_std::time::Duration;
use std::cell::RefMut;
use std::collections::HashSet;
use std::convert::{TryFrom, TryInto};
use std::io::{IoSlice, IoSliceMut};
use std::ops::Deref;
@@ -778,7 +780,11 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
}
let table = self.table();
let mut poll = Poll::new(&table);
let mut sub_fds: HashSet<types::Fd> = HashSet::new();
// We need these refmuts to outlive Poll, which will hold the &mut dyn WasiFile inside
let mut read_refs: Vec<(RefMut<'_, dyn WasiFile>, Userdata)> = Vec::new();
let mut write_refs: Vec<(RefMut<'_, dyn WasiFile>, Userdata)> = Vec::new();
let mut poll = Poll::new();
let subs = subs.as_array(nsubscriptions);
for sub_elem in subs.iter() {
@@ -816,11 +822,29 @@ impl wasi_unstable::WasiUnstable for WasiCtx {
},
types::SubscriptionU::FdRead(readsub) => {
let fd = readsub.file_descriptor;
poll.subscribe_read(u32::from(fd), sub.userdata.into())?;
if sub_fds.contains(&fd) {
return Err(Error::invalid_argument()
.context("Fd can be subscribed to at most once per poll"));
} else {
sub_fds.insert(fd);
}
let file_ref = table
.get_file_mut(u32::from(fd))?
.get_cap(FileCaps::POLL_READWRITE)?;
read_refs.push((file_ref, sub.userdata.into()));
}
types::SubscriptionU::FdWrite(writesub) => {
let fd = writesub.file_descriptor;
poll.subscribe_write(u32::from(fd), sub.userdata.into())?;
if sub_fds.contains(&fd) {
return Err(Error::invalid_argument()
.context("Fd can be subscribed to at most once per poll"));
} else {
sub_fds.insert(fd);
}
let file_ref = table
.get_file_mut(u32::from(fd))?
.get_cap(FileCaps::POLL_READWRITE)?;
write_refs.push((file_ref, sub.userdata.into()));
}
}
}