Skip to content

Commit 0cb050f

Browse files
committed
WIP: use Arc<Self> in WasiFile and associated traits
This is an attempt to apply @alexcrichton's comment [here](bytecodealliance#5326 (comment)) which proposed using `self: &Arc<Self>` in the `WasiFile` trait. This change, made as `self: Arc<Self>` here due to Rust method receiver limitations, affects many locations. E.g., `WasiDir` also needs to start using `Arc<Self>`, etc. This results in a slew of errors at all the use locations. This commit fixes up many of these but is marked "WIP" since not all are fixed; the latest challenge is deciding what the signature of `WasiFile::pollable` should be when the switch to `Arc<Self>` is made.
1 parent 09487b0 commit 0cb050f

File tree

13 files changed

+273
-265
lines changed

13 files changed

+273
-265
lines changed

crates/wasi-common/cap-std-sync/src/dir.rs

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::file::{filetype_from, File};
22
use cap_fs_ext::{DirEntryExt, DirExt, MetadataExt, SystemTimeSpec};
33
use std::any::Any;
44
use std::path::{Path, PathBuf};
5+
use std::sync::Arc;
56
use system_interface::fs::GetSetFdFlags;
67
use wasi_common::{
78
dir::{ReaddirCursor, ReaddirEntity, WasiDir},
@@ -109,33 +110,37 @@ impl Dir {
109110

110111
#[async_trait::async_trait]
111112
impl WasiDir for Dir {
112-
fn as_any(&self) -> &dyn Any {
113+
fn as_any(self: Arc<Self>) -> Arc<dyn Any> {
113114
self
114115
}
115116
async fn open_file(
116-
&self,
117+
self: Arc<Self>,
117118
symlink_follow: bool,
118119
path: &str,
119120
oflags: OFlags,
120121
read: bool,
121122
write: bool,
122123
fdflags: FdFlags,
123-
) -> Result<Box<dyn WasiFile>, Error> {
124+
) -> Result<Arc<dyn WasiFile>, Error> {
124125
let f = self.open_file_(symlink_follow, path, oflags, read, write, fdflags)?;
125-
Ok(Box::new(f))
126+
Ok(Arc::new(f))
126127
}
127128

128-
async fn open_dir(&self, symlink_follow: bool, path: &str) -> Result<Box<dyn WasiDir>, Error> {
129+
async fn open_dir(
130+
self: Arc<Self>,
131+
symlink_follow: bool,
132+
path: &str,
133+
) -> Result<Arc<dyn WasiDir>, Error> {
129134
let d = self.open_dir_(symlink_follow, path)?;
130-
Ok(Box::new(d))
135+
Ok(Arc::new(d))
131136
}
132137

133-
async fn create_dir(&self, path: &str) -> Result<(), Error> {
138+
async fn create_dir(self: Arc<Self>, path: &str) -> Result<(), Error> {
134139
self.0.create_dir(Path::new(path))?;
135140
Ok(())
136141
}
137142
async fn readdir(
138-
&self,
143+
self: Arc<Self>,
139144
cursor: ReaddirCursor,
140145
) -> Result<Box<dyn Iterator<Item = Result<ReaddirEntity, Error>> + Send>, Error> {
141146
// We need to keep a full-fidelity io Error around to check for a special failure mode
@@ -216,24 +221,24 @@ impl WasiDir for Dir {
216221
Ok(Box::new(rd))
217222
}
218223

219-
async fn symlink(&self, src_path: &str, dest_path: &str) -> Result<(), Error> {
224+
async fn symlink(self: Arc<Self>, src_path: &str, dest_path: &str) -> Result<(), Error> {
220225
self.0.symlink(src_path, dest_path)?;
221226
Ok(())
222227
}
223-
async fn remove_dir(&self, path: &str) -> Result<(), Error> {
228+
async fn remove_dir(self: Arc<Self>, path: &str) -> Result<(), Error> {
224229
self.0.remove_dir(Path::new(path))?;
225230
Ok(())
226231
}
227232

228-
async fn unlink_file(&self, path: &str) -> Result<(), Error> {
233+
async fn unlink_file(self: Arc<Self>, path: &str) -> Result<(), Error> {
229234
self.0.remove_file_or_symlink(Path::new(path))?;
230235
Ok(())
231236
}
232-
async fn read_link(&self, path: &str) -> Result<PathBuf, Error> {
237+
async fn read_link(self: Arc<Self>, path: &str) -> Result<PathBuf, Error> {
233238
let link = self.0.read_link(Path::new(path))?;
234239
Ok(link)
235240
}
236-
async fn get_filestat(&self) -> Result<Filestat, Error> {
241+
async fn get_filestat(self: Arc<Self>) -> Result<Filestat, Error> {
237242
let meta = self.0.dir_metadata()?;
238243
Ok(Filestat {
239244
device_id: meta.dev(),
@@ -247,7 +252,7 @@ impl WasiDir for Dir {
247252
})
248253
}
249254
async fn get_path_filestat(
250-
&self,
255+
self: Arc<Self>,
251256
path: &str,
252257
follow_symlinks: bool,
253258
) -> Result<Filestat, Error> {
@@ -268,9 +273,9 @@ impl WasiDir for Dir {
268273
})
269274
}
270275
async fn rename(
271-
&self,
276+
self: Arc<Self>,
272277
src_path: &str,
273-
dest_dir: &dyn WasiDir,
278+
dest_dir: Arc<dyn WasiDir>,
274279
dest_path: &str,
275280
) -> Result<(), Error> {
276281
let dest_dir = dest_dir
@@ -280,9 +285,9 @@ impl WasiDir for Dir {
280285
self.rename_(src_path, dest_dir, dest_path)
281286
}
282287
async fn hard_link(
283-
&self,
288+
self: Arc<Self>,
284289
src_path: &str,
285-
target_dir: &dyn WasiDir,
290+
target_dir: Arc<dyn WasiDir>,
286291
target_path: &str,
287292
) -> Result<(), Error> {
288293
let target_dir = target_dir
@@ -292,7 +297,7 @@ impl WasiDir for Dir {
292297
self.hard_link_(src_path, target_dir, target_path)
293298
}
294299
async fn set_times(
295-
&self,
300+
self: Arc<Self>,
296301
path: &str,
297302
atime: Option<wasi_common::SystemTimeSpec>,
298303
mtime: Option<wasi_common::SystemTimeSpec>,

crates/wasi-common/cap-std-sync/src/file.rs

Lines changed: 49 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -24,90 +24,63 @@ use io_lifetimes::{AsHandle, BorrowedHandle};
2424
#[cfg(windows)]
2525
use io_extras::os::windows::{AsRawHandleOrSocket, RawHandleOrSocket};
2626

27-
pub struct BorrowedFile<'a>(RwLockReadGuard<'a, cap_std::fs::File>);
28-
29-
#[cfg(unix)]
30-
impl AsFd for BorrowedFile<'_> {
31-
fn as_fd(&self) -> BorrowedFd<'_> {
32-
self.0.as_fd()
33-
}
34-
}
35-
36-
#[cfg(windows)]
37-
impl AsHandle for BorrowedFile<'_> {
38-
fn as_handle(&self) -> BorrowedHandle<'_> {
39-
self.0.as_handle()
40-
}
41-
}
42-
43-
#[cfg(windows)]
44-
impl AsRawHandleOrSocket for BorrowedFile<'_> {
45-
#[inline]
46-
fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
47-
self.0.as_raw_handle_or_socket()
48-
}
49-
}
50-
51-
pub struct File(RwLock<cap_std::fs::File>);
27+
pub struct File(cap_std::fs::File);
5228

5329
impl File {
5430
pub fn from_cap_std(file: cap_std::fs::File) -> Self {
55-
File(RwLock::new(file))
56-
}
57-
58-
pub fn borrow(&self) -> BorrowedFile {
59-
BorrowedFile(self.0.read().unwrap())
31+
File(file)
6032
}
6133
}
6234

6335
#[async_trait::async_trait]
6436
impl WasiFile for File {
65-
fn as_any(&self) -> &dyn Any {
37+
fn as_any(self: Arc<Self>) -> Arc<dyn Any> {
6638
self
6739
}
6840

6941
#[cfg(unix)]
70-
fn pollable(&self) -> Option<Arc<dyn AsFd + '_>> {
71-
Some(Arc::new(self.borrow()))
42+
fn pollable(self: Arc<Self>) -> Option<Arc<dyn AsFd>> {
43+
Some(Arc::new(self.0.as_fd()))
7244
}
7345

7446
#[cfg(windows)]
75-
fn pollable(&self) -> Option<Arc<dyn AsRawHandleOrSocket + '_>> {
76-
Some(Arc::new(BorrowedFile(self.0.read().unwrap())))
47+
fn pollable(self: Arc<Self>) -> Option<Arc<dyn AsRawHandleOrSocket>> {
48+
Some(Arc::new(BorrowedFile(self.0)))
7749
}
7850

79-
async fn datasync(&self) -> Result<(), Error> {
80-
self.0.read().unwrap().sync_data()?;
51+
async fn datasync(self: Arc<Self>) -> Result<(), Error> {
52+
self.0.sync_data()?;
8153
Ok(())
8254
}
83-
async fn sync(&self) -> Result<(), Error> {
84-
self.0.read().unwrap().sync_all()?;
55+
async fn sync(self: Arc<Self>) -> Result<(), Error> {
56+
self.0.sync_all()?;
8557
Ok(())
8658
}
87-
async fn get_filetype(&self) -> Result<FileType, Error> {
88-
let meta = self.0.read().unwrap().metadata()?;
59+
async fn get_filetype(self: Arc<Self>) -> Result<FileType, Error> {
60+
let meta = self.0.metadata()?;
8961
Ok(filetype_from(&meta.file_type()))
9062
}
91-
async fn get_fdflags(&self) -> Result<FdFlags, Error> {
92-
let file = self.0.read().unwrap();
93-
let fdflags = get_fd_flags(&*file)?;
63+
async fn get_fdflags(self: Arc<Self>) -> Result<FdFlags, Error> {
64+
let fdflags = get_fd_flags(self.0)?;
9465
Ok(fdflags)
9566
}
96-
async fn set_fdflags(&self, fdflags: FdFlags) -> Result<(), Error> {
67+
async fn set_fdflags(mut self: Arc<Self>, fdflags: FdFlags) -> Result<(), Error> {
9768
if fdflags.intersects(
9869
wasi_common::file::FdFlags::DSYNC
9970
| wasi_common::file::FdFlags::SYNC
10071
| wasi_common::file::FdFlags::RSYNC,
10172
) {
10273
return Err(Error::invalid_argument().context("cannot set DSYNC, SYNC, or RSYNC flag"));
10374
}
104-
let mut file = self.0.write().unwrap();
105-
let set_fd_flags = (*file).new_set_fd_flags(to_sysif_fdflags(fdflags))?;
106-
(*file).set_fd_flags(set_fd_flags)?;
75+
let set_fd_flags = self.0.new_set_fd_flags(to_sysif_fdflags(fdflags))?;
76+
Arc::get_mut(&mut self)
77+
.unwrap()
78+
.0
79+
.set_fd_flags(set_fd_flags)?;
10780
Ok(())
10881
}
109-
async fn get_filestat(&self) -> Result<Filestat, Error> {
110-
let meta = self.0.read().unwrap().metadata()?;
82+
async fn get_filestat(self: Arc<Self>) -> Result<Filestat, Error> {
83+
let meta = self.0.metadata()?;
11184
Ok(Filestat {
11285
device_id: meta.dev(),
11386
inode: meta.ino(),
@@ -119,68 +92,66 @@ impl WasiFile for File {
11992
ctim: meta.created().map(|t| Some(t.into_std())).unwrap_or(None),
12093
})
12194
}
122-
async fn set_filestat_size(&self, size: u64) -> Result<(), Error> {
123-
self.0.read().unwrap().set_len(size)?;
95+
async fn set_filestat_size(self: Arc<Self>, size: u64) -> Result<(), Error> {
96+
self.0.set_len(size)?;
12497
Ok(())
12598
}
126-
async fn advise(&self, offset: u64, len: u64, advice: Advice) -> Result<(), Error> {
127-
self.0
128-
.read()
129-
.unwrap()
130-
.advise(offset, len, convert_advice(advice))?;
99+
async fn advise(self: Arc<Self>, offset: u64, len: u64, advice: Advice) -> Result<(), Error> {
100+
self.0.advise(offset, len, convert_advice(advice))?;
131101
Ok(())
132102
}
133-
async fn allocate(&self, offset: u64, len: u64) -> Result<(), Error> {
134-
self.0.read().unwrap().allocate(offset, len)?;
103+
async fn allocate(self: Arc<Self>, offset: u64, len: u64) -> Result<(), Error> {
104+
self.0.allocate(offset, len)?;
135105
Ok(())
136106
}
137107
async fn set_times(
138-
&self,
108+
self: Arc<Self>,
139109
atime: Option<wasi_common::SystemTimeSpec>,
140110
mtime: Option<wasi_common::SystemTimeSpec>,
141111
) -> Result<(), Error> {
142112
self.0
143-
.read()
144-
.unwrap()
145113
.set_times(convert_systimespec(atime), convert_systimespec(mtime))?;
146114
Ok(())
147115
}
148-
async fn read_vectored<'a>(&self, bufs: &mut [io::IoSliceMut<'a>]) -> Result<u64, Error> {
149-
let n = self.0.read().unwrap().read_vectored(bufs)?;
116+
async fn read_vectored<'a>(
117+
self: Arc<Self>,
118+
bufs: &mut [io::IoSliceMut<'a>],
119+
) -> Result<u64, Error> {
120+
let n = self.0.read_vectored(bufs)?;
150121
Ok(n.try_into()?)
151122
}
152123
async fn read_vectored_at<'a>(
153-
&self,
124+
self: Arc<Self>,
154125
bufs: &mut [io::IoSliceMut<'a>],
155126
offset: u64,
156127
) -> Result<u64, Error> {
157-
let n = self.0.read().unwrap().read_vectored_at(bufs, offset)?;
128+
let n = self.0.read_vectored_at(bufs, offset)?;
158129
Ok(n.try_into()?)
159130
}
160-
async fn write_vectored<'a>(&self, bufs: &[io::IoSlice<'a>]) -> Result<u64, Error> {
161-
let n = self.0.read().unwrap().write_vectored(bufs)?;
131+
async fn write_vectored<'a>(self: Arc<Self>, bufs: &[io::IoSlice<'a>]) -> Result<u64, Error> {
132+
let n = self.0.write_vectored(bufs)?;
162133
Ok(n.try_into()?)
163134
}
164135
async fn write_vectored_at<'a>(
165-
&self,
136+
self: Arc<Self>,
166137
bufs: &[io::IoSlice<'a>],
167138
offset: u64,
168139
) -> Result<u64, Error> {
169-
let n = self.0.read().unwrap().write_vectored_at(bufs, offset)?;
140+
let n = self.0.write_vectored_at(bufs, offset)?;
170141
Ok(n.try_into()?)
171142
}
172-
async fn seek(&self, pos: std::io::SeekFrom) -> Result<u64, Error> {
173-
Ok(self.0.read().unwrap().seek(pos)?)
143+
async fn seek(self: Arc<Self>, pos: std::io::SeekFrom) -> Result<u64, Error> {
144+
Ok(self.0.seek(pos)?)
174145
}
175-
async fn peek(&self, buf: &mut [u8]) -> Result<u64, Error> {
176-
let n = self.0.read().unwrap().peek(buf)?;
146+
async fn peek(self: Arc<Self>, buf: &mut [u8]) -> Result<u64, Error> {
147+
let n = self.0.peek(buf)?;
177148
Ok(n.try_into()?)
178149
}
179-
fn num_ready_bytes(&self) -> Result<u64, Error> {
180-
Ok(self.0.read().unwrap().num_ready_bytes()?)
150+
fn num_ready_bytes(self: Arc<Self>) -> Result<u64, Error> {
151+
Ok(self.0.num_ready_bytes()?)
181152
}
182-
fn isatty(&self) -> bool {
183-
self.0.read().unwrap().is_terminal()
153+
fn isatty(self: Arc<Self>) -> bool {
154+
self.0.is_terminal()
184155
}
185156
}
186157

crates/wasi-common/cap-std-sync/src/lib.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ pub use sched::sched_ctx;
4848

4949
use crate::net::Socket;
5050
use cap_rand::{Rng, RngCore, SeedableRng};
51-
use std::path::Path;
51+
use std::{path::Path, sync::Arc};
5252
use wasi_common::{file::FileCaps, table::Table, Error, WasiCtx, WasiFile};
5353

5454
pub struct WasiCtxBuilder(WasiCtx);
@@ -94,38 +94,38 @@ impl WasiCtxBuilder {
9494
}
9595
Ok(self)
9696
}
97-
pub fn stdin(self, f: Box<dyn WasiFile>) -> Self {
97+
pub fn stdin(self, f: Arc<dyn WasiFile>) -> Self {
9898
self.0.set_stdin(f);
9999
self
100100
}
101-
pub fn stdout(self, f: Box<dyn WasiFile>) -> Self {
101+
pub fn stdout(self, f: Arc<dyn WasiFile>) -> Self {
102102
self.0.set_stdout(f);
103103
self
104104
}
105-
pub fn stderr(self, f: Box<dyn WasiFile>) -> Self {
105+
pub fn stderr(self, f: Arc<dyn WasiFile>) -> Self {
106106
self.0.set_stderr(f);
107107
self
108108
}
109109
pub fn inherit_stdin(self) -> Self {
110-
self.stdin(Box::new(crate::stdio::stdin()))
110+
self.stdin(Arc::new(crate::stdio::stdin()))
111111
}
112112
pub fn inherit_stdout(self) -> Self {
113-
self.stdout(Box::new(crate::stdio::stdout()))
113+
self.stdout(Arc::new(crate::stdio::stdout()))
114114
}
115115
pub fn inherit_stderr(self) -> Self {
116-
self.stderr(Box::new(crate::stdio::stderr()))
116+
self.stderr(Arc::new(crate::stdio::stderr()))
117117
}
118118
pub fn inherit_stdio(self) -> Self {
119119
self.inherit_stdin().inherit_stdout().inherit_stderr()
120120
}
121121
pub fn preopened_dir(self, dir: Dir, guest_path: impl AsRef<Path>) -> Result<Self, Error> {
122-
let dir = Box::new(crate::dir::Dir::from_cap_std(dir));
122+
let dir = Arc::new(crate::dir::Dir::from_cap_std(dir));
123123
self.0.push_preopened_dir(dir, guest_path)?;
124124
Ok(self)
125125
}
126126
pub fn preopened_socket(self, fd: u32, socket: impl Into<Socket>) -> Result<Self, Error> {
127127
let socket: Socket = socket.into();
128-
let file: Box<dyn WasiFile> = socket.into();
128+
let file: Arc<dyn WasiFile> = socket.into();
129129

130130
let caps = FileCaps::FDSTAT_SET_FLAGS
131131
| FileCaps::FILESTAT_GET

0 commit comments

Comments
 (0)