mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-08 13:48:26 +00:00
Many bug fixes and performance optimizations
- Removed generation_arena which was causing some serious leakages of files and sockets - Added OsError for NetworkErrors so that "Too Many Open Files" is properly passed - Local networking will now cap at 10 sockets in the backlog - Added the missing shutdown error code - Removed the inodes lock around most of the WASI syscalls - Fixed some race conditions in the event notifications for WASI - The polling loop will now only notify a closed socket once - Event notifications now uses Wakers rather than MPSC - Some socket errors now return the right codes which prevents panics in WASM - Fixed a bug where the file read and write guards might release the file before the lock - The inode seed is now much safer preventing overlaps - The fd seed is now much safer preventing overlaps - Closing files is now implicit rather than explicit reducing possibliities for error - Forking of file descriptors is now much simplier - Polling events will now be returned in random order to prevent some race conditions - Removed a number of memory allocations which were wasting memory and performance - Sockets now only copy the send and recv data once rather than multiple times
This commit is contained in:
61
Cargo.lock
generated
61
Cargo.lock
generated
@@ -125,6 +125,15 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atomic-polyfill"
|
||||||
|
version = "0.1.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28"
|
||||||
|
dependencies = [
|
||||||
|
"critical-section",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atty"
|
name = "atty"
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
@@ -732,6 +741,12 @@ dependencies = [
|
|||||||
"itertools",
|
"itertools",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "critical-section"
|
||||||
|
version = "1.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.5.6"
|
version = "0.5.6"
|
||||||
@@ -1332,16 +1347,6 @@ dependencies = [
|
|||||||
"byteorder",
|
"byteorder",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "generational-arena"
|
|
||||||
version = "0.2.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8e1d3b771574f62d0548cee0ad9057857e9fc25d7a3335f140c84f6acd0bf601"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if 0.1.10",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.14.6"
|
version = "0.14.6"
|
||||||
@@ -1511,6 +1516,15 @@ version = "1.8.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
|
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hash32"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.11.2"
|
version = "0.11.2"
|
||||||
@@ -1538,6 +1552,19 @@ dependencies = [
|
|||||||
"hashbrown 0.12.3",
|
"hashbrown 0.12.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heapless"
|
||||||
|
version = "0.7.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743"
|
||||||
|
dependencies = [
|
||||||
|
"atomic-polyfill",
|
||||||
|
"hash32",
|
||||||
|
"rustc_version 0.4.0",
|
||||||
|
"spin 0.9.5",
|
||||||
|
"stable_deref_trait",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
@@ -2985,7 +3012,7 @@ dependencies = [
|
|||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"spin",
|
"spin 0.5.2",
|
||||||
"untrusted",
|
"untrusted",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
"winapi",
|
"winapi",
|
||||||
@@ -3506,6 +3533,15 @@ version = "0.5.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.9.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7dccf47db1b41fa1573ed27ccf5e08e3ca771cb994f776668c5ebda893b248fc"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spinoff"
|
name = "spinoff"
|
||||||
version = "0.5.4"
|
version = "0.5.4"
|
||||||
@@ -5135,6 +5171,7 @@ dependencies = [
|
|||||||
"async-trait",
|
"async-trait",
|
||||||
"bytes",
|
"bytes",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"tracing",
|
||||||
"wasmer-vfs",
|
"wasmer-vfs",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -5151,8 +5188,8 @@ dependencies = [
|
|||||||
"cooked-waker",
|
"cooked-waker",
|
||||||
"derivative",
|
"derivative",
|
||||||
"futures",
|
"futures",
|
||||||
"generational-arena",
|
|
||||||
"getrandom",
|
"getrandom",
|
||||||
|
"heapless",
|
||||||
"hex",
|
"hex",
|
||||||
"http",
|
"http",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ thiserror = "1"
|
|||||||
wasmer-vfs = { path = "../vfs", version = "=3.2.0-alpha.1", default-features = false }
|
wasmer-vfs = { path = "../vfs", version = "=3.2.0-alpha.1", default-features = false }
|
||||||
bytes = "1"
|
bytes = "1"
|
||||||
async-trait = { version = "^0.1" }
|
async-trait = { version = "^0.1" }
|
||||||
|
tracing = "0.1"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
|
|||||||
@@ -554,6 +554,9 @@ pub enum NetworkError {
|
|||||||
/// A call to write returned 0
|
/// A call to write returned 0
|
||||||
#[error("write returned 0")]
|
#[error("write returned 0")]
|
||||||
WriteZero,
|
WriteZero,
|
||||||
|
/// OS error
|
||||||
|
#[error("operating system error({0})")]
|
||||||
|
OsError(i32),
|
||||||
/// The operation is not supported.
|
/// The operation is not supported.
|
||||||
#[error("unsupported")]
|
#[error("unsupported")]
|
||||||
Unsupported,
|
Unsupported,
|
||||||
@@ -563,6 +566,7 @@ pub enum NetworkError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn net_error_into_io_err(net_error: NetworkError) -> std::io::Error {
|
pub fn net_error_into_io_err(net_error: NetworkError) -> std::io::Error {
|
||||||
|
use std::io::Error;
|
||||||
use std::io::ErrorKind;
|
use std::io::ErrorKind;
|
||||||
match net_error {
|
match net_error {
|
||||||
NetworkError::InvalidFd => ErrorKind::BrokenPipe.into(),
|
NetworkError::InvalidFd => ErrorKind::BrokenPipe.into(),
|
||||||
@@ -585,6 +589,7 @@ pub fn net_error_into_io_err(net_error: NetworkError) -> std::io::Error {
|
|||||||
NetworkError::UnexpectedEof => ErrorKind::UnexpectedEof.into(),
|
NetworkError::UnexpectedEof => ErrorKind::UnexpectedEof.into(),
|
||||||
NetworkError::WouldBlock => ErrorKind::WouldBlock.into(),
|
NetworkError::WouldBlock => ErrorKind::WouldBlock.into(),
|
||||||
NetworkError::WriteZero => ErrorKind::WriteZero.into(),
|
NetworkError::WriteZero => ErrorKind::WriteZero.into(),
|
||||||
|
NetworkError::OsError(code) => Error::from_raw_os_error(code),
|
||||||
NetworkError::Unsupported => ErrorKind::Unsupported.into(),
|
NetworkError::Unsupported => ErrorKind::Unsupported.into(),
|
||||||
NetworkError::UnknownError => ErrorKind::BrokenPipe.into(),
|
NetworkError::UnknownError => ErrorKind::BrokenPipe.into(),
|
||||||
}
|
}
|
||||||
@@ -610,6 +615,12 @@ pub fn io_err_into_net_error(net_error: std::io::Error) -> NetworkError {
|
|||||||
ErrorKind::WouldBlock => NetworkError::WouldBlock,
|
ErrorKind::WouldBlock => NetworkError::WouldBlock,
|
||||||
ErrorKind::WriteZero => NetworkError::WriteZero,
|
ErrorKind::WriteZero => NetworkError::WriteZero,
|
||||||
ErrorKind::Unsupported => NetworkError::Unsupported,
|
ErrorKind::Unsupported => NetworkError::Unsupported,
|
||||||
_ => NetworkError::UnknownError,
|
_ => {
|
||||||
|
if let Some(code) = net_error.raw_os_error() {
|
||||||
|
NetworkError::OsError(code)
|
||||||
|
} else {
|
||||||
|
NetworkError::UnknownError
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,6 @@ use wasmer_wasi::os::fs::WasiFs;
|
|||||||
use wasmer_wasi::os::fs::WasiInodes;
|
use wasmer_wasi::os::fs::WasiInodes;
|
||||||
|
|
||||||
#[cfg(not(feature = "link_external_libs"))]
|
#[cfg(not(feature = "link_external_libs"))]
|
||||||
pub fn initialize(_: &mut WasiInodes, _: &mut WasiFs) -> Result<(), String> {
|
pub fn initialize(_: &WasiInodes, _: &mut WasiFs) -> Result<(), String> {
|
||||||
Err("wasi-experimental-io-devices has to be compiled with --features=\"link_external_libs\" (not enabled by default) for graphics I/O to work".to_string())
|
Err("wasi-experimental-io-devices has to be compiled with --features=\"link_external_libs\" (not enabled by default) for graphics I/O to work".to_string())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -430,7 +430,7 @@ impl VirtualFile for FrameBuffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initialize(inodes: &mut WasiInodes, fs: &mut WasiFs) -> Result<(), String> {
|
pub fn initialize(inodes: &WasiInodes, fs: &mut WasiFs) -> Result<(), String> {
|
||||||
let frame_buffer_file = Box::new(FrameBuffer {
|
let frame_buffer_file = Box::new(FrameBuffer {
|
||||||
fb_type: FrameBufferFileType::Buffer,
|
fb_type: FrameBufferFileType::Buffer,
|
||||||
cursor: 0,
|
cursor: 0,
|
||||||
|
|||||||
@@ -140,6 +140,12 @@ impl VirtualTcpListener for LocalTcpListener {
|
|||||||
&mut self,
|
&mut self,
|
||||||
cx: &mut std::task::Context<'_>,
|
cx: &mut std::task::Context<'_>,
|
||||||
) -> std::task::Poll<Result<usize>> {
|
) -> std::task::Poll<Result<usize>> {
|
||||||
|
{
|
||||||
|
let backlog = self.backlog.lock().unwrap();
|
||||||
|
if backlog.len() > 10 {
|
||||||
|
return Poll::Ready(Ok(backlog.len()));
|
||||||
|
}
|
||||||
|
}
|
||||||
self.stream
|
self.stream
|
||||||
.poll_accept(cx)
|
.poll_accept(cx)
|
||||||
.map_err(io_err_into_net_error)
|
.map_err(io_err_into_net_error)
|
||||||
|
|||||||
@@ -245,6 +245,8 @@ enum errno {
|
|||||||
xdev,
|
xdev,
|
||||||
/// Extension: Capabilities insufficient.
|
/// Extension: Capabilities insufficient.
|
||||||
notcapable,
|
notcapable,
|
||||||
|
/// Cannot send after socket shutdown.
|
||||||
|
shutdown,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum bus-errno {
|
enum bus-errno {
|
||||||
|
|||||||
@@ -246,6 +246,8 @@ pub enum Errno {
|
|||||||
Xdev,
|
Xdev,
|
||||||
#[doc = " Extension: Capabilities insufficient."]
|
#[doc = " Extension: Capabilities insufficient."]
|
||||||
Notcapable,
|
Notcapable,
|
||||||
|
#[doc = " Cannot send after socket shutdown."]
|
||||||
|
Shutdown,
|
||||||
}
|
}
|
||||||
impl Errno {
|
impl Errno {
|
||||||
pub fn name(&self) -> &'static str {
|
pub fn name(&self) -> &'static str {
|
||||||
@@ -327,6 +329,7 @@ impl Errno {
|
|||||||
Errno::Txtbsy => "txtbsy",
|
Errno::Txtbsy => "txtbsy",
|
||||||
Errno::Xdev => "xdev",
|
Errno::Xdev => "xdev",
|
||||||
Errno::Notcapable => "notcapable",
|
Errno::Notcapable => "notcapable",
|
||||||
|
Errno::Shutdown => "shutdown",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn message(&self) -> &'static str {
|
pub fn message(&self) -> &'static str {
|
||||||
@@ -408,6 +411,7 @@ impl Errno {
|
|||||||
Errno::Txtbsy => "Text file busy.",
|
Errno::Txtbsy => "Text file busy.",
|
||||||
Errno::Xdev => "Cross-device link.",
|
Errno::Xdev => "Cross-device link.",
|
||||||
Errno::Notcapable => "Extension: Capabilities insufficient.",
|
Errno::Notcapable => "Extension: Capabilities insufficient.",
|
||||||
|
Errno::Shutdown => "Cannot send after socket shutdown.",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
cfg-if = "1.0"
|
cfg-if = "1.0"
|
||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
generational-arena = { version = "0.2" }
|
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
getrandom = "0.2"
|
getrandom = "0.2"
|
||||||
wasmer-wasi-types = { path = "../wasi-types", version = "=3.2.0-alpha.1" }
|
wasmer-wasi-types = { path = "../wasi-types", version = "=3.2.0-alpha.1" }
|
||||||
@@ -61,6 +60,7 @@ wasmer-compiler-singlepass = { version = "=3.2.0-alpha.1", path = "../compiler-s
|
|||||||
wasmer-compiler = { version = "=3.2.0-alpha.1", path = "../compiler", features = [ "translator" ], optional = true }
|
wasmer-compiler = { version = "=3.2.0-alpha.1", path = "../compiler", features = [ "translator" ], optional = true }
|
||||||
http = "0.2.8"
|
http = "0.2.8"
|
||||||
wai-bindgen-wasmer = { path = "../wai-bindgen-wasmer", version = "0.2.3", features = ["tracing"] }
|
wai-bindgen-wasmer = { path = "../wai-bindgen-wasmer", version = "0.2.3", features = ["tracing"] }
|
||||||
|
heapless = "0.7.16"
|
||||||
|
|
||||||
[dependencies.reqwest]
|
[dependencies.reqwest]
|
||||||
version = "0.11"
|
version = "0.11"
|
||||||
@@ -125,6 +125,5 @@ disable-all-logging = [
|
|||||||
enable-serde = [
|
enable-serde = [
|
||||||
"typetag",
|
"typetag",
|
||||||
"wasmer-vfs/enable-serde",
|
"wasmer-vfs/enable-serde",
|
||||||
"generational-arena/serde",
|
|
||||||
"wasmer-wasi-types/enable-serde",
|
"wasmer-wasi-types/enable-serde",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -2,13 +2,10 @@ use std::{
|
|||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
collections::{HashMap, VecDeque},
|
collections::{HashMap, VecDeque},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
sync::{
|
sync::{atomic::AtomicU64, Arc, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard},
|
||||||
atomic::{AtomicBool, AtomicU32, AtomicU64},
|
task::Waker,
|
||||||
Arc, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use generational_arena::Index as Inode;
|
|
||||||
#[cfg(feature = "enable-serde")]
|
#[cfg(feature = "enable-serde")]
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use wasmer_vfs::{VirtualFile, WasiPipe};
|
use wasmer_vfs::{VirtualFile, WasiPipe};
|
||||||
@@ -16,12 +13,11 @@ use wasmer_wasi_types::wasi::{Fd as WasiFd, Fdflags, Filestat, Rights};
|
|||||||
|
|
||||||
use crate::net::socket::InodeSocket;
|
use crate::net::socket::InodeSocket;
|
||||||
|
|
||||||
|
use super::{InodeGuard, InodeWeakGuard};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub struct Fd {
|
pub struct Fd {
|
||||||
/// The reference count is only increased when the FD is
|
|
||||||
/// duplicates - fd_close will not kill the inode until this reaches zero
|
|
||||||
pub ref_cnt: Arc<AtomicU32>,
|
|
||||||
pub rights: Rights,
|
pub rights: Rights,
|
||||||
pub rights_inheriting: Rights,
|
pub rights_inheriting: Rights,
|
||||||
pub flags: Fdflags,
|
pub flags: Fdflags,
|
||||||
@@ -30,7 +26,7 @@ pub struct Fd {
|
|||||||
///
|
///
|
||||||
/// Used when reopening a [`VirtualFile`] during [`WasiState`] deserialization.
|
/// Used when reopening a [`VirtualFile`] during [`WasiState`] deserialization.
|
||||||
pub open_flags: u16,
|
pub open_flags: u16,
|
||||||
pub inode: Inode,
|
pub inode: InodeGuard,
|
||||||
pub is_stdio: bool,
|
pub is_stdio: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,6 +70,21 @@ impl InodeVal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
|
pub struct NotificationInner {
|
||||||
|
/// Used for event notifications by the user application or operating system
|
||||||
|
/// (positive number means there are events waiting to be processed)
|
||||||
|
pub counter: AtomicU64,
|
||||||
|
/// Counter used to prevent duplicate notification events
|
||||||
|
pub last_poll: AtomicU64,
|
||||||
|
/// Flag that indicates if this is operating
|
||||||
|
pub is_semaphore: bool,
|
||||||
|
/// Receiver that wakes sleeping threads
|
||||||
|
#[cfg_attr(feature = "enable-serde", serde(skip))]
|
||||||
|
pub wakers: Mutex<VecDeque<Waker>>,
|
||||||
|
}
|
||||||
|
|
||||||
/// The core of the filesystem abstraction. Includes directories,
|
/// The core of the filesystem abstraction. Includes directories,
|
||||||
/// files, and symlinks.
|
/// files, and symlinks.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -104,19 +115,19 @@ pub enum Kind {
|
|||||||
},
|
},
|
||||||
Dir {
|
Dir {
|
||||||
/// Parent directory
|
/// Parent directory
|
||||||
parent: Option<Inode>,
|
parent: InodeWeakGuard,
|
||||||
/// The path on the host system where the directory is located
|
/// The path on the host system where the directory is located
|
||||||
// TODO: wrap it like VirtualFile
|
// TODO: wrap it like VirtualFile
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
/// The entries of a directory are lazily filled.
|
/// The entries of a directory are lazily filled.
|
||||||
entries: HashMap<String, Inode>,
|
entries: HashMap<String, InodeGuard>,
|
||||||
},
|
},
|
||||||
/// The same as Dir but without the irrelevant bits
|
/// The same as Dir but without the irrelevant bits
|
||||||
/// The root is immutable after creation; generally the Kind::Root
|
/// The root is immutable after creation; generally the Kind::Root
|
||||||
/// branch of whatever code you're writing will be a simpler version of
|
/// branch of whatever code you're writing will be a simpler version of
|
||||||
/// your Kind::Dir logic
|
/// your Kind::Dir logic
|
||||||
Root {
|
Root {
|
||||||
entries: HashMap<String, Inode>,
|
entries: HashMap<String, InodeGuard>,
|
||||||
},
|
},
|
||||||
/// The first two fields are data _about_ the symlink
|
/// The first two fields are data _about_ the symlink
|
||||||
/// the last field is the data _inside_ the symlink
|
/// the last field is the data _inside_ the symlink
|
||||||
@@ -135,16 +146,5 @@ pub enum Kind {
|
|||||||
Buffer {
|
Buffer {
|
||||||
buffer: Vec<u8>,
|
buffer: Vec<u8>,
|
||||||
},
|
},
|
||||||
EventNotifications {
|
EventNotifications(Arc<NotificationInner>),
|
||||||
/// Used for event notifications by the user application or operating system
|
|
||||||
/// (positive number means there are events waiting to be processed)
|
|
||||||
counter: Arc<AtomicU64>,
|
|
||||||
/// Flag that indicates if this is operating
|
|
||||||
is_semaphore: bool,
|
|
||||||
/// Receiver that wakes sleeping threads
|
|
||||||
#[cfg_attr(feature = "enable-serde", serde(skip))]
|
|
||||||
wakers: Arc<Mutex<VecDeque<tokio::sync::mpsc::UnboundedSender<()>>>>,
|
|
||||||
/// Immediate waker
|
|
||||||
immediate: Arc<AtomicBool>,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,17 +3,11 @@ use std::{
|
|||||||
io::{IoSlice, SeekFrom},
|
io::{IoSlice, SeekFrom},
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
sync::{
|
sync::{atomic::Ordering, Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
|
||||||
atomic::{AtomicU64, Ordering},
|
|
||||||
Arc, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard,
|
|
||||||
},
|
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
};
|
};
|
||||||
|
|
||||||
use tokio::{
|
use tokio::io::{AsyncRead, AsyncSeek, AsyncWrite};
|
||||||
io::{AsyncRead, AsyncSeek, AsyncWrite},
|
|
||||||
sync::mpsc,
|
|
||||||
};
|
|
||||||
use wasmer_vfs::{FsError, VirtualFile};
|
use wasmer_vfs::{FsError, VirtualFile};
|
||||||
use wasmer_vnet::{net_error_into_io_err, NetworkError};
|
use wasmer_vnet::{net_error_into_io_err, NetworkError};
|
||||||
use wasmer_wasi_types::{
|
use wasmer_wasi_types::{
|
||||||
@@ -22,24 +16,18 @@ use wasmer_wasi_types::{
|
|||||||
wasi::{Errno, Event, EventFdReadwrite, EventUnion, Eventrwflags, Subscription},
|
wasi::{Errno, Event, EventFdReadwrite, EventUnion, Eventrwflags, Subscription},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::Kind;
|
use super::{fd::NotificationInner, InodeGuard, Kind};
|
||||||
use crate::{
|
use crate::{
|
||||||
net::socket::{InodeSocketInner, InodeSocketKind},
|
net::socket::{InodeSocketInner, InodeSocketKind},
|
||||||
state::{iterate_poll_events, PollEvent, PollEventSet},
|
state::{iterate_poll_events, PollEvent, PollEventSet},
|
||||||
syscalls::map_io_err,
|
syscalls::map_io_err,
|
||||||
WasiInodes, WasiState,
|
WasiState,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) enum InodeValFilePollGuardMode {
|
pub(crate) enum InodeValFilePollGuardMode {
|
||||||
File(Arc<RwLock<Box<dyn VirtualFile + Send + Sync + 'static>>>),
|
File(Arc<RwLock<Box<dyn VirtualFile + Send + Sync + 'static>>>),
|
||||||
EventNotifications {
|
EventNotifications(Arc<NotificationInner>),
|
||||||
immediate: bool,
|
Socket { inner: Arc<InodeSocketInner> },
|
||||||
waker: Mutex<mpsc::UnboundedReceiver<()>>,
|
|
||||||
counter: Arc<AtomicU64>,
|
|
||||||
},
|
|
||||||
Socket {
|
|
||||||
inner: Arc<RwLock<InodeSocketInner>>,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct InodeValFilePollGuard {
|
pub(crate) struct InodeValFilePollGuard {
|
||||||
@@ -57,25 +45,8 @@ impl InodeValFilePollGuard {
|
|||||||
guard: &Kind,
|
guard: &Kind,
|
||||||
) -> Option<Self> {
|
) -> Option<Self> {
|
||||||
let mode = match guard.deref() {
|
let mode = match guard.deref() {
|
||||||
Kind::EventNotifications {
|
Kind::EventNotifications(inner) => {
|
||||||
counter,
|
InodeValFilePollGuardMode::EventNotifications(inner.clone())
|
||||||
wakers,
|
|
||||||
immediate,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let (tx, rx) = tokio::sync::mpsc::unbounded_channel();
|
|
||||||
let immediate = {
|
|
||||||
let mut wakers = wakers.lock().unwrap();
|
|
||||||
wakers.push_back(tx);
|
|
||||||
immediate
|
|
||||||
.compare_exchange(true, false, Ordering::AcqRel, Ordering::Relaxed)
|
|
||||||
.is_ok()
|
|
||||||
};
|
|
||||||
InodeValFilePollGuardMode::EventNotifications {
|
|
||||||
immediate,
|
|
||||||
waker: Mutex::new(rx),
|
|
||||||
counter: counter.clone(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Kind::Socket { socket } => InodeValFilePollGuardMode::Socket {
|
Kind::Socket { socket } => InodeValFilePollGuardMode::Socket {
|
||||||
inner: socket.inner.clone(),
|
inner: socket.inner.clone(),
|
||||||
@@ -105,7 +76,7 @@ impl std::fmt::Debug for InodeValFilePollGuard {
|
|||||||
write!(f, "guard-notifications")
|
write!(f, "guard-notifications")
|
||||||
}
|
}
|
||||||
InodeValFilePollGuardMode::Socket { inner } => {
|
InodeValFilePollGuardMode::Socket { inner } => {
|
||||||
let inner = inner.read().unwrap();
|
let inner = inner.protected.read().unwrap();
|
||||||
match inner.kind {
|
match inner.kind {
|
||||||
InodeSocketKind::TcpListener { .. } => write!(f, "guard-tcp-listener"),
|
InodeSocketKind::TcpListener { .. } => write!(f, "guard-tcp-listener"),
|
||||||
InodeSocketKind::TcpStream { ref socket, .. } => {
|
InodeSocketKind::TcpStream { ref socket, .. } => {
|
||||||
@@ -125,20 +96,6 @@ impl std::fmt::Debug for InodeValFilePollGuard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InodeValFilePollGuard {
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn is_open(&self) -> bool {
|
|
||||||
match &self.mode {
|
|
||||||
InodeValFilePollGuardMode::File(file) => {
|
|
||||||
let guard = file.read().unwrap();
|
|
||||||
guard.is_open()
|
|
||||||
}
|
|
||||||
InodeValFilePollGuardMode::EventNotifications { .. }
|
|
||||||
| InodeValFilePollGuardMode::Socket { .. } => true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) struct InodeValFilePollGuardJoin<'a> {
|
pub(crate) struct InodeValFilePollGuardJoin<'a> {
|
||||||
mode: &'a mut InodeValFilePollGuardMode,
|
mode: &'a mut InodeValFilePollGuardMode,
|
||||||
fd: u32,
|
fd: u32,
|
||||||
@@ -161,14 +118,17 @@ impl<'a> InodeValFilePollGuardJoin<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Future for InodeValFilePollGuardJoin<'a> {
|
impl<'a> Future for InodeValFilePollGuardJoin<'a> {
|
||||||
type Output = Event;
|
type Output = heapless::Vec<Event, 4>;
|
||||||
|
|
||||||
fn poll(mut self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
|
fn poll(mut self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
|
||||||
|
let fd = self.fd();
|
||||||
|
let waker = cx.waker();
|
||||||
let mut has_read = false;
|
let mut has_read = false;
|
||||||
let mut has_write = false;
|
let mut has_write = false;
|
||||||
let mut has_close = false;
|
let mut has_close = false;
|
||||||
let mut has_hangup = false;
|
let mut has_hangup = false;
|
||||||
|
|
||||||
|
let mut ret = heapless::Vec::new();
|
||||||
for in_event in iterate_poll_events(self.peb) {
|
for in_event in iterate_poll_events(self.peb) {
|
||||||
match in_event {
|
match in_event {
|
||||||
PollEvent::PollIn => {
|
PollEvent::PollIn => {
|
||||||
@@ -197,10 +157,8 @@ impl<'a> Future for InodeValFilePollGuardJoin<'a> {
|
|||||||
}
|
}
|
||||||
InodeValFilePollGuardMode::EventNotifications { .. } => false,
|
InodeValFilePollGuardMode::EventNotifications { .. } => false,
|
||||||
InodeValFilePollGuardMode::Socket { ref inner } => {
|
InodeValFilePollGuardMode::Socket { ref inner } => {
|
||||||
let mut guard = inner.write().unwrap();
|
let mut guard = inner.protected.write().unwrap();
|
||||||
let is_closed = if let InodeSocketKind::Closed = guard.kind {
|
let is_closed = if has_read || has_write {
|
||||||
true
|
|
||||||
} else if has_read || has_write {
|
|
||||||
// this will be handled in the read/write poll instead
|
// this will be handled in the read/write poll instead
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
@@ -217,11 +175,15 @@ impl<'a> Future for InodeValFilePollGuardJoin<'a> {
|
|||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
is_closed
|
if is_closed {
|
||||||
|
std::mem::replace(&mut guard.notifications.closed, true) == false
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if is_closed {
|
if is_closed {
|
||||||
return Poll::Ready(Event {
|
ret.push(Event {
|
||||||
userdata: self.subscription.userdata,
|
userdata: self.subscription.userdata,
|
||||||
error: Errno::Success,
|
error: Errno::Success,
|
||||||
type_: self.subscription.type_,
|
type_: self.subscription.type_,
|
||||||
@@ -238,192 +200,211 @@ impl<'a> Future for InodeValFilePollGuardJoin<'a> {
|
|||||||
},
|
},
|
||||||
Eventtype::Clock => EventUnion { clock: 0 },
|
Eventtype::Clock => EventUnion { clock: 0 },
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if has_read {
|
if has_read {
|
||||||
let mut poll_result = match &mut self.mode {
|
let poll_result = match &mut self.mode {
|
||||||
InodeValFilePollGuardMode::File(file) => {
|
InodeValFilePollGuardMode::File(file) => {
|
||||||
let mut guard = file.write().unwrap();
|
let mut guard = file.write().unwrap();
|
||||||
let file = Pin::new(guard.as_mut());
|
let file = Pin::new(guard.as_mut());
|
||||||
file.poll_read_ready(cx)
|
file.poll_read_ready(cx)
|
||||||
}
|
}
|
||||||
InodeValFilePollGuardMode::EventNotifications {
|
InodeValFilePollGuardMode::EventNotifications(inner) => {
|
||||||
waker,
|
{
|
||||||
counter,
|
let mut guard = inner.wakers.lock().unwrap();
|
||||||
immediate,
|
if guard.iter().any(|a| a.will_wake(waker)) == false {
|
||||||
..
|
guard.push_front(waker.clone());
|
||||||
} => {
|
}
|
||||||
if *immediate {
|
}
|
||||||
let cnt = counter.load(Ordering::Acquire);
|
let val = inner.counter.load(Ordering::Acquire);
|
||||||
Poll::Ready(Ok(cnt as usize))
|
if inner.last_poll.swap(val, Ordering::AcqRel) != val {
|
||||||
|
Poll::Ready(Ok(val as usize))
|
||||||
} else {
|
} else {
|
||||||
let counter = counter.clone();
|
Poll::Pending
|
||||||
let mut waker = waker.lock().unwrap();
|
|
||||||
let mut notifications = Pin::new(waker.deref_mut());
|
|
||||||
notifications.poll_recv(cx).map(|_| {
|
|
||||||
let cnt = counter.load(Ordering::Acquire);
|
|
||||||
Ok(cnt as usize)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InodeValFilePollGuardMode::Socket { ref inner } => {
|
InodeValFilePollGuardMode::Socket { ref inner } => {
|
||||||
let mut guard = inner.write().unwrap();
|
let mut guard = inner.protected.write().unwrap();
|
||||||
guard.poll_read_ready(cx).map_err(net_error_into_io_err)
|
let res = guard.poll_read_ready(cx).map_err(net_error_into_io_err);
|
||||||
|
match res {
|
||||||
|
Poll::Ready(Err(err)) if is_err_closed(&err) => {
|
||||||
|
tracing::trace!("socket read ready error (fd={}) - {}", fd, err);
|
||||||
|
if std::mem::replace(&mut guard.notifications.closed, true) == false {
|
||||||
|
Poll::Ready(Ok(0))
|
||||||
|
} else {
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Poll::Ready(Err(err)) => {
|
||||||
|
tracing::debug!("poll socket error - {}", err);
|
||||||
|
if std::mem::replace(&mut guard.notifications.failed, true) == false {
|
||||||
|
Poll::Ready(Ok(0))
|
||||||
|
} else {
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res => res,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if has_close {
|
match poll_result {
|
||||||
poll_result = match poll_result {
|
Poll::Ready(Err(err)) if has_close && is_err_closed(&err) => {
|
||||||
Poll::Ready(Err(err))
|
ret.push(Event {
|
||||||
if err.kind() == std::io::ErrorKind::ConnectionAborted
|
userdata: self.subscription.userdata,
|
||||||
|| err.kind() == std::io::ErrorKind::ConnectionRefused
|
error: Errno::Success,
|
||||||
|| err.kind() == std::io::ErrorKind::ConnectionReset
|
type_: self.subscription.type_,
|
||||||
|| err.kind() == std::io::ErrorKind::BrokenPipe
|
u: match self.subscription.type_ {
|
||||||
|| err.kind() == std::io::ErrorKind::NotConnected
|
Eventtype::FdRead | Eventtype::FdWrite => EventUnion {
|
||||||
|| err.kind() == std::io::ErrorKind::UnexpectedEof =>
|
fd_readwrite: EventFdReadwrite {
|
||||||
{
|
nbytes: 0,
|
||||||
return Poll::Ready(Event {
|
flags: if has_hangup {
|
||||||
userdata: self.subscription.userdata,
|
Eventrwflags::FD_READWRITE_HANGUP
|
||||||
error: Errno::Success,
|
} else {
|
||||||
type_: self.subscription.type_,
|
Eventrwflags::empty()
|
||||||
u: match self.subscription.type_ {
|
|
||||||
Eventtype::FdRead | Eventtype::FdWrite => EventUnion {
|
|
||||||
fd_readwrite: EventFdReadwrite {
|
|
||||||
nbytes: 0,
|
|
||||||
flags: if has_hangup {
|
|
||||||
Eventrwflags::FD_READWRITE_HANGUP
|
|
||||||
} else {
|
|
||||||
Eventrwflags::empty()
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Eventtype::Clock => EventUnion { clock: 0 },
|
|
||||||
},
|
},
|
||||||
});
|
Eventtype::Clock => EventUnion { clock: 0 },
|
||||||
}
|
},
|
||||||
a => a,
|
})
|
||||||
};
|
.ok();
|
||||||
}
|
}
|
||||||
if let Poll::Ready(bytes_available) = poll_result {
|
Poll::Ready(bytes_available) => {
|
||||||
let mut error = Errno::Success;
|
let mut error = Errno::Success;
|
||||||
let bytes_available = match bytes_available {
|
let bytes_available = match bytes_available {
|
||||||
Ok(a) => a,
|
Ok(a) => a,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error = map_io_err(e);
|
error = map_io_err(e);
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return Poll::Ready(Event {
|
ret.push(Event {
|
||||||
userdata: self.subscription.userdata,
|
userdata: self.subscription.userdata,
|
||||||
error,
|
error,
|
||||||
type_: self.subscription.type_,
|
type_: self.subscription.type_,
|
||||||
u: match self.subscription.type_ {
|
u: match self.subscription.type_ {
|
||||||
Eventtype::FdRead | Eventtype::FdWrite => EventUnion {
|
Eventtype::FdRead | Eventtype::FdWrite => EventUnion {
|
||||||
fd_readwrite: EventFdReadwrite {
|
fd_readwrite: EventFdReadwrite {
|
||||||
nbytes: bytes_available as u64,
|
nbytes: bytes_available as u64,
|
||||||
flags: if bytes_available == 0 {
|
flags: if bytes_available == 0 {
|
||||||
Eventrwflags::FD_READWRITE_HANGUP
|
Eventrwflags::FD_READWRITE_HANGUP
|
||||||
} else {
|
} else {
|
||||||
Eventrwflags::empty()
|
Eventrwflags::empty()
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Eventtype::Clock => EventUnion { clock: 0 },
|
||||||
},
|
},
|
||||||
Eventtype::Clock => EventUnion { clock: 0 },
|
})
|
||||||
},
|
.ok();
|
||||||
});
|
}
|
||||||
}
|
Poll::Pending => {}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if has_write {
|
if has_write {
|
||||||
let mut poll_result = match &mut self.mode {
|
let poll_result = match &mut self.mode {
|
||||||
InodeValFilePollGuardMode::File(file) => {
|
InodeValFilePollGuardMode::File(file) => {
|
||||||
let mut guard = file.write().unwrap();
|
let mut guard = file.write().unwrap();
|
||||||
let file = Pin::new(guard.as_mut());
|
let file = Pin::new(guard.as_mut());
|
||||||
file.poll_write_ready(cx)
|
file.poll_write_ready(cx)
|
||||||
}
|
}
|
||||||
InodeValFilePollGuardMode::EventNotifications {
|
InodeValFilePollGuardMode::EventNotifications(inner) => {
|
||||||
waker,
|
{
|
||||||
counter,
|
let mut guard = inner.wakers.lock().unwrap();
|
||||||
immediate,
|
if guard.iter().any(|a| a.will_wake(waker)) == false {
|
||||||
..
|
guard.push_front(waker.clone());
|
||||||
} => {
|
}
|
||||||
if *immediate {
|
}
|
||||||
let cnt = counter.load(Ordering::Acquire);
|
let val = inner.counter.load(Ordering::Acquire);
|
||||||
Poll::Ready(Ok(cnt as usize))
|
if inner.last_poll.swap(val, Ordering::AcqRel) != val {
|
||||||
|
Poll::Ready(Ok(val as usize))
|
||||||
} else {
|
} else {
|
||||||
let counter = counter.clone();
|
Poll::Pending
|
||||||
let mut waker = waker.lock().unwrap();
|
|
||||||
let mut notifications = Pin::new(waker.deref_mut());
|
|
||||||
notifications.poll_recv(cx).map(|_| {
|
|
||||||
let cnt = counter.load(Ordering::Acquire);
|
|
||||||
Ok(cnt as usize)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InodeValFilePollGuardMode::Socket { ref inner } => {
|
InodeValFilePollGuardMode::Socket { ref inner } => {
|
||||||
let mut guard = inner.write().unwrap();
|
let mut guard = inner.protected.write().unwrap();
|
||||||
guard.poll_write_ready(cx).map_err(net_error_into_io_err)
|
let res = guard.poll_write_ready(cx).map_err(net_error_into_io_err);
|
||||||
|
match res {
|
||||||
|
Poll::Ready(Err(err)) if is_err_closed(&err) => {
|
||||||
|
tracing::trace!("socket write ready error (fd={}) - {}", fd, err);
|
||||||
|
if std::mem::replace(&mut guard.notifications.closed, true) == false {
|
||||||
|
Poll::Ready(Ok(0))
|
||||||
|
} else {
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Poll::Ready(Err(err)) => {
|
||||||
|
tracing::debug!("poll socket error - {}", err);
|
||||||
|
if std::mem::replace(&mut guard.notifications.failed, true) == false {
|
||||||
|
Poll::Ready(Ok(0))
|
||||||
|
} else {
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res => res,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if has_close {
|
match poll_result {
|
||||||
poll_result = match poll_result {
|
Poll::Ready(Err(err)) if has_close && is_err_closed(&err) => {
|
||||||
Poll::Ready(Err(err))
|
ret.push(Event {
|
||||||
if err.kind() == std::io::ErrorKind::ConnectionAborted
|
userdata: self.subscription.userdata,
|
||||||
|| err.kind() == std::io::ErrorKind::ConnectionRefused
|
error: Errno::Success,
|
||||||
|| err.kind() == std::io::ErrorKind::ConnectionReset
|
type_: self.subscription.type_,
|
||||||
|| err.kind() == std::io::ErrorKind::BrokenPipe
|
u: match self.subscription.type_ {
|
||||||
|| err.kind() == std::io::ErrorKind::NotConnected
|
Eventtype::FdRead | Eventtype::FdWrite => EventUnion {
|
||||||
|| err.kind() == std::io::ErrorKind::UnexpectedEof =>
|
fd_readwrite: EventFdReadwrite {
|
||||||
{
|
nbytes: 0,
|
||||||
return Poll::Ready(Event {
|
flags: if has_hangup {
|
||||||
userdata: self.subscription.userdata,
|
Eventrwflags::FD_READWRITE_HANGUP
|
||||||
error: Errno::Success,
|
} else {
|
||||||
type_: self.subscription.type_,
|
Eventrwflags::empty()
|
||||||
u: match self.subscription.type_ {
|
|
||||||
Eventtype::FdRead | Eventtype::FdWrite => EventUnion {
|
|
||||||
fd_readwrite: EventFdReadwrite {
|
|
||||||
nbytes: 0,
|
|
||||||
flags: if has_hangup {
|
|
||||||
Eventrwflags::FD_READWRITE_HANGUP
|
|
||||||
} else {
|
|
||||||
Eventrwflags::empty()
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Eventtype::Clock => EventUnion { clock: 0 },
|
|
||||||
},
|
},
|
||||||
});
|
Eventtype::Clock => EventUnion { clock: 0 },
|
||||||
}
|
},
|
||||||
a => a,
|
})
|
||||||
};
|
.ok();
|
||||||
}
|
}
|
||||||
if let Poll::Ready(bytes_available) = poll_result {
|
Poll::Ready(bytes_available) => {
|
||||||
let mut error = Errno::Success;
|
let mut error = Errno::Success;
|
||||||
let bytes_available = match bytes_available {
|
let bytes_available = match bytes_available {
|
||||||
Ok(a) => a,
|
Ok(a) => a,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error = map_io_err(e);
|
error = map_io_err(e);
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return Poll::Ready(Event {
|
ret.push(Event {
|
||||||
userdata: self.subscription.userdata,
|
userdata: self.subscription.userdata,
|
||||||
error,
|
error,
|
||||||
type_: self.subscription.type_,
|
type_: self.subscription.type_,
|
||||||
u: match self.subscription.type_ {
|
u: match self.subscription.type_ {
|
||||||
Eventtype::FdRead | Eventtype::FdWrite => EventUnion {
|
Eventtype::FdRead | Eventtype::FdWrite => EventUnion {
|
||||||
fd_readwrite: EventFdReadwrite {
|
fd_readwrite: EventFdReadwrite {
|
||||||
nbytes: bytes_available as u64,
|
nbytes: bytes_available as u64,
|
||||||
flags: if bytes_available == 0 {
|
flags: if bytes_available == 0 {
|
||||||
Eventrwflags::FD_READWRITE_HANGUP
|
Eventrwflags::FD_READWRITE_HANGUP
|
||||||
} else {
|
} else {
|
||||||
Eventrwflags::empty()
|
Eventrwflags::empty()
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Eventtype::Clock => EventUnion { clock: 0 },
|
||||||
},
|
},
|
||||||
Eventtype::Clock => EventUnion { clock: 0 },
|
})
|
||||||
},
|
.ok();
|
||||||
});
|
}
|
||||||
}
|
Poll::Pending => {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if ret.len() > 0 {
|
||||||
|
return Poll::Ready(ret);
|
||||||
}
|
}
|
||||||
Poll::Pending
|
Poll::Pending
|
||||||
}
|
}
|
||||||
@@ -431,16 +412,18 @@ impl<'a> Future for InodeValFilePollGuardJoin<'a> {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct InodeValFileReadGuard {
|
pub(crate) struct InodeValFileReadGuard {
|
||||||
#[allow(dead_code)]
|
|
||||||
file: Arc<RwLock<Box<dyn VirtualFile + Send + Sync + 'static>>>,
|
|
||||||
guard: RwLockReadGuard<'static, Box<dyn VirtualFile + Send + Sync + 'static>>,
|
guard: RwLockReadGuard<'static, Box<dyn VirtualFile + Send + Sync + 'static>>,
|
||||||
|
// we must keep a reference as the lifetime of the guard becomes owned using unsafe code
|
||||||
|
// (warning!! The fields of a struct are dropped in declaration order thus this must be at the end)
|
||||||
|
// (https://doc.rust-lang.org/reference/destructors.html#:~:text=The%20fields%20of%20a%20struct,first%20element%20to%20the%20last.)
|
||||||
|
_file: Arc<RwLock<Box<dyn VirtualFile + Send + Sync + 'static>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InodeValFileReadGuard {
|
impl InodeValFileReadGuard {
|
||||||
pub(crate) fn new(file: &Arc<RwLock<Box<dyn VirtualFile + Send + Sync + 'static>>>) -> Self {
|
pub(crate) fn new(file: &Arc<RwLock<Box<dyn VirtualFile + Send + Sync + 'static>>>) -> Self {
|
||||||
let guard = file.read().unwrap();
|
let guard = file.read().unwrap();
|
||||||
Self {
|
Self {
|
||||||
file: file.clone(),
|
_file: file.clone(),
|
||||||
guard: unsafe { std::mem::transmute(guard) },
|
guard: unsafe { std::mem::transmute(guard) },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -457,7 +440,7 @@ impl InodeValFileReadGuard {
|
|||||||
fd,
|
fd,
|
||||||
peb,
|
peb,
|
||||||
subscription,
|
subscription,
|
||||||
mode: InodeValFilePollGuardMode::File(self.file),
|
mode: InodeValFilePollGuardMode::File(self._file),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -471,16 +454,18 @@ impl Deref for InodeValFileReadGuard {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct InodeValFileWriteGuard {
|
pub struct InodeValFileWriteGuard {
|
||||||
#[allow(dead_code)]
|
|
||||||
file: Arc<RwLock<Box<dyn VirtualFile + Send + Sync + 'static>>>,
|
|
||||||
guard: RwLockWriteGuard<'static, Box<dyn VirtualFile + Send + Sync + 'static>>,
|
guard: RwLockWriteGuard<'static, Box<dyn VirtualFile + Send + Sync + 'static>>,
|
||||||
|
// we must keep a reference as the lifetime of the guard becomes owned using unsafe code
|
||||||
|
// (warning!! The fields of a struct are dropped in declaration order thus this must be at the end)
|
||||||
|
// (https://doc.rust-lang.org/reference/destructors.html#:~:text=The%20fields%20of%20a%20struct,first%20element%20to%20the%20last.)
|
||||||
|
_file: Arc<RwLock<Box<dyn VirtualFile + Send + Sync + 'static>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InodeValFileWriteGuard {
|
impl InodeValFileWriteGuard {
|
||||||
pub(crate) fn new(file: &Arc<RwLock<Box<dyn VirtualFile + Send + Sync + 'static>>>) -> Self {
|
pub(crate) fn new(file: &Arc<RwLock<Box<dyn VirtualFile + Send + Sync + 'static>>>) -> Self {
|
||||||
let guard = file.write().unwrap();
|
let guard = file.write().unwrap();
|
||||||
Self {
|
Self {
|
||||||
file: file.clone(),
|
_file: file.clone(),
|
||||||
guard: unsafe { std::mem::transmute(guard) },
|
guard: unsafe { std::mem::transmute(guard) },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -507,32 +492,23 @@ impl DerefMut for InodeValFileWriteGuard {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct WasiStateFileGuard {
|
pub(crate) struct WasiStateFileGuard {
|
||||||
inodes: Arc<RwLock<WasiInodes>>,
|
inode: InodeGuard,
|
||||||
inode: generational_arena::Index,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WasiStateFileGuard {
|
impl WasiStateFileGuard {
|
||||||
pub fn new(state: &WasiState, fd: wasi::Fd) -> Result<Option<Self>, FsError> {
|
pub fn new(state: &WasiState, fd: wasi::Fd) -> Result<Option<Self>, FsError> {
|
||||||
let inodes = state.inodes.read().unwrap();
|
|
||||||
let fd_map = state.fs.fd_map.read().unwrap();
|
let fd_map = state.fs.fd_map.read().unwrap();
|
||||||
if let Some(fd) = fd_map.get(&fd) {
|
if let Some(fd) = fd_map.get(&fd) {
|
||||||
let guard = inodes.arena[fd.inode].read();
|
Ok(Some(Self {
|
||||||
if let Kind::File { .. } = guard.deref() {
|
inode: fd.inode.clone(),
|
||||||
Ok(Some(Self {
|
}))
|
||||||
inodes: state.inodes.clone(),
|
|
||||||
inode: fd.inode,
|
|
||||||
}))
|
|
||||||
} else {
|
|
||||||
// Our public API should ensure that this is not possible
|
|
||||||
Err(FsError::NotAFile)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lock_read(&self, inodes: &RwLockReadGuard<WasiInodes>) -> Option<InodeValFileReadGuard> {
|
pub fn lock_read(&self) -> Option<InodeValFileReadGuard> {
|
||||||
let guard = inodes.arena[self.inode].read();
|
let guard = self.inode.read();
|
||||||
if let Kind::File { handle, .. } = guard.deref() {
|
if let Kind::File { handle, .. } = guard.deref() {
|
||||||
handle.as_ref().map(InodeValFileReadGuard::new)
|
handle.as_ref().map(InodeValFileReadGuard::new)
|
||||||
} else {
|
} else {
|
||||||
@@ -541,11 +517,8 @@ impl WasiStateFileGuard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lock_write(
|
pub fn lock_write(&self) -> Option<InodeValFileWriteGuard> {
|
||||||
&self,
|
let guard = self.inode.read();
|
||||||
inodes: &RwLockReadGuard<WasiInodes>,
|
|
||||||
) -> Option<InodeValFileWriteGuard> {
|
|
||||||
let guard = inodes.arena[self.inode].read();
|
|
||||||
if let Kind::File { handle, .. } = guard.deref() {
|
if let Kind::File { handle, .. } = guard.deref() {
|
||||||
handle.as_ref().map(InodeValFileWriteGuard::new)
|
handle.as_ref().map(InodeValFileWriteGuard::new)
|
||||||
} else {
|
} else {
|
||||||
@@ -557,8 +530,7 @@ impl WasiStateFileGuard {
|
|||||||
|
|
||||||
impl VirtualFile for WasiStateFileGuard {
|
impl VirtualFile for WasiStateFileGuard {
|
||||||
fn last_accessed(&self) -> u64 {
|
fn last_accessed(&self) -> u64 {
|
||||||
let inodes = self.inodes.read().unwrap();
|
let guard = self.lock_read();
|
||||||
let guard = self.lock_read(&inodes);
|
|
||||||
if let Some(file) = guard.as_ref() {
|
if let Some(file) = guard.as_ref() {
|
||||||
file.last_accessed()
|
file.last_accessed()
|
||||||
} else {
|
} else {
|
||||||
@@ -567,8 +539,7 @@ impl VirtualFile for WasiStateFileGuard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn last_modified(&self) -> u64 {
|
fn last_modified(&self) -> u64 {
|
||||||
let inodes = self.inodes.read().unwrap();
|
let guard = self.lock_read();
|
||||||
let guard = self.lock_read(&inodes);
|
|
||||||
if let Some(file) = guard.as_ref() {
|
if let Some(file) = guard.as_ref() {
|
||||||
file.last_modified()
|
file.last_modified()
|
||||||
} else {
|
} else {
|
||||||
@@ -577,8 +548,7 @@ impl VirtualFile for WasiStateFileGuard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn created_time(&self) -> u64 {
|
fn created_time(&self) -> u64 {
|
||||||
let inodes = self.inodes.read().unwrap();
|
let guard = self.lock_read();
|
||||||
let guard = self.lock_read(&inodes);
|
|
||||||
if let Some(file) = guard.as_ref() {
|
if let Some(file) = guard.as_ref() {
|
||||||
file.created_time()
|
file.created_time()
|
||||||
} else {
|
} else {
|
||||||
@@ -587,8 +557,7 @@ impl VirtualFile for WasiStateFileGuard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn size(&self) -> u64 {
|
fn size(&self) -> u64 {
|
||||||
let inodes = self.inodes.read().unwrap();
|
let guard = self.lock_read();
|
||||||
let guard = self.lock_read(&inodes);
|
|
||||||
if let Some(file) = guard.as_ref() {
|
if let Some(file) = guard.as_ref() {
|
||||||
file.size()
|
file.size()
|
||||||
} else {
|
} else {
|
||||||
@@ -597,8 +566,7 @@ impl VirtualFile for WasiStateFileGuard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn set_len(&mut self, new_size: u64) -> Result<(), FsError> {
|
fn set_len(&mut self, new_size: u64) -> Result<(), FsError> {
|
||||||
let inodes = self.inodes.read().unwrap();
|
let mut guard = self.lock_write();
|
||||||
let mut guard = self.lock_write(&inodes);
|
|
||||||
if let Some(file) = guard.as_mut() {
|
if let Some(file) = guard.as_mut() {
|
||||||
file.set_len(new_size)
|
file.set_len(new_size)
|
||||||
} else {
|
} else {
|
||||||
@@ -607,8 +575,7 @@ impl VirtualFile for WasiStateFileGuard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn unlink(&mut self) -> Result<(), FsError> {
|
fn unlink(&mut self) -> Result<(), FsError> {
|
||||||
let inodes = self.inodes.read().unwrap();
|
let mut guard = self.lock_write();
|
||||||
let mut guard = self.lock_write(&inodes);
|
|
||||||
if let Some(file) = guard.as_mut() {
|
if let Some(file) = guard.as_mut() {
|
||||||
file.unlink()
|
file.unlink()
|
||||||
} else {
|
} else {
|
||||||
@@ -617,8 +584,7 @@ impl VirtualFile for WasiStateFileGuard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_open(&self) -> bool {
|
fn is_open(&self) -> bool {
|
||||||
let inodes = self.inodes.read().unwrap();
|
let guard = self.lock_read();
|
||||||
let guard = self.lock_read(&inodes);
|
|
||||||
if let Some(file) = guard.as_ref() {
|
if let Some(file) = guard.as_ref() {
|
||||||
file.is_open()
|
file.is_open()
|
||||||
} else {
|
} else {
|
||||||
@@ -627,8 +593,7 @@ impl VirtualFile for WasiStateFileGuard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn poll_read_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<usize>> {
|
fn poll_read_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<usize>> {
|
||||||
let inodes = self.inodes.read().unwrap();
|
let mut guard = self.lock_write();
|
||||||
let mut guard = self.lock_write(&inodes);
|
|
||||||
if let Some(file) = guard.as_mut() {
|
if let Some(file) = guard.as_mut() {
|
||||||
let file = Pin::new(file.deref_mut());
|
let file = Pin::new(file.deref_mut());
|
||||||
file.poll_read_ready(cx)
|
file.poll_read_ready(cx)
|
||||||
@@ -641,8 +606,7 @@ impl VirtualFile for WasiStateFileGuard {
|
|||||||
self: Pin<&mut Self>,
|
self: Pin<&mut Self>,
|
||||||
cx: &mut Context<'_>,
|
cx: &mut Context<'_>,
|
||||||
) -> Poll<std::io::Result<usize>> {
|
) -> Poll<std::io::Result<usize>> {
|
||||||
let inodes = self.inodes.read().unwrap();
|
let mut guard = self.lock_write();
|
||||||
let mut guard = self.lock_write(&inodes);
|
|
||||||
if let Some(file) = guard.as_mut() {
|
if let Some(file) = guard.as_mut() {
|
||||||
let file = Pin::new(file.deref_mut());
|
let file = Pin::new(file.deref_mut());
|
||||||
file.poll_write_ready(cx)
|
file.poll_write_ready(cx)
|
||||||
@@ -654,8 +618,7 @@ impl VirtualFile for WasiStateFileGuard {
|
|||||||
|
|
||||||
impl AsyncSeek for WasiStateFileGuard {
|
impl AsyncSeek for WasiStateFileGuard {
|
||||||
fn start_seek(self: Pin<&mut Self>, position: SeekFrom) -> std::io::Result<()> {
|
fn start_seek(self: Pin<&mut Self>, position: SeekFrom) -> std::io::Result<()> {
|
||||||
let inodes = self.inodes.read().unwrap();
|
let mut guard = self.lock_write();
|
||||||
let mut guard = self.lock_write(&inodes);
|
|
||||||
if let Some(guard) = guard.as_mut() {
|
if let Some(guard) = guard.as_mut() {
|
||||||
let file = Pin::new(guard.deref_mut());
|
let file = Pin::new(guard.deref_mut());
|
||||||
file.start_seek(position)
|
file.start_seek(position)
|
||||||
@@ -664,8 +627,7 @@ impl AsyncSeek for WasiStateFileGuard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn poll_complete(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<u64>> {
|
fn poll_complete(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<u64>> {
|
||||||
let inodes = self.inodes.read().unwrap();
|
let mut guard = self.lock_write();
|
||||||
let mut guard = self.lock_write(&inodes);
|
|
||||||
if let Some(guard) = guard.as_mut() {
|
if let Some(guard) = guard.as_mut() {
|
||||||
let file = Pin::new(guard.deref_mut());
|
let file = Pin::new(guard.deref_mut());
|
||||||
file.poll_complete(cx)
|
file.poll_complete(cx)
|
||||||
@@ -681,8 +643,7 @@ impl AsyncWrite for WasiStateFileGuard {
|
|||||||
cx: &mut Context<'_>,
|
cx: &mut Context<'_>,
|
||||||
buf: &[u8],
|
buf: &[u8],
|
||||||
) -> Poll<std::io::Result<usize>> {
|
) -> Poll<std::io::Result<usize>> {
|
||||||
let inodes = self.inodes.read().unwrap();
|
let mut guard = self.lock_write();
|
||||||
let mut guard = self.lock_write(&inodes);
|
|
||||||
if let Some(guard) = guard.as_mut() {
|
if let Some(guard) = guard.as_mut() {
|
||||||
let file = Pin::new(guard.deref_mut());
|
let file = Pin::new(guard.deref_mut());
|
||||||
file.poll_write(cx, buf)
|
file.poll_write(cx, buf)
|
||||||
@@ -691,8 +652,7 @@ impl AsyncWrite for WasiStateFileGuard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
|
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
|
||||||
let inodes = self.inodes.read().unwrap();
|
let mut guard = self.lock_write();
|
||||||
let mut guard = self.lock_write(&inodes);
|
|
||||||
if let Some(guard) = guard.as_mut() {
|
if let Some(guard) = guard.as_mut() {
|
||||||
let file = Pin::new(guard.deref_mut());
|
let file = Pin::new(guard.deref_mut());
|
||||||
file.poll_flush(cx)
|
file.poll_flush(cx)
|
||||||
@@ -701,8 +661,7 @@ impl AsyncWrite for WasiStateFileGuard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
|
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
|
||||||
let inodes = self.inodes.read().unwrap();
|
let mut guard = self.lock_write();
|
||||||
let mut guard = self.lock_write(&inodes);
|
|
||||||
if let Some(guard) = guard.as_mut() {
|
if let Some(guard) = guard.as_mut() {
|
||||||
let file = Pin::new(guard.deref_mut());
|
let file = Pin::new(guard.deref_mut());
|
||||||
file.poll_shutdown(cx)
|
file.poll_shutdown(cx)
|
||||||
@@ -715,8 +674,7 @@ impl AsyncWrite for WasiStateFileGuard {
|
|||||||
cx: &mut Context<'_>,
|
cx: &mut Context<'_>,
|
||||||
bufs: &[IoSlice<'_>],
|
bufs: &[IoSlice<'_>],
|
||||||
) -> Poll<std::io::Result<usize>> {
|
) -> Poll<std::io::Result<usize>> {
|
||||||
let inodes = self.inodes.read().unwrap();
|
let mut guard = self.lock_write();
|
||||||
let mut guard = self.lock_write(&inodes);
|
|
||||||
if let Some(guard) = guard.as_mut() {
|
if let Some(guard) = guard.as_mut() {
|
||||||
let file = Pin::new(guard.deref_mut());
|
let file = Pin::new(guard.deref_mut());
|
||||||
file.poll_write_vectored(cx, bufs)
|
file.poll_write_vectored(cx, bufs)
|
||||||
@@ -725,8 +683,7 @@ impl AsyncWrite for WasiStateFileGuard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn is_write_vectored(&self) -> bool {
|
fn is_write_vectored(&self) -> bool {
|
||||||
let inodes = self.inodes.read().unwrap();
|
let mut guard = self.lock_write();
|
||||||
let mut guard = self.lock_write(&inodes);
|
|
||||||
if let Some(guard) = guard.as_mut() {
|
if let Some(guard) = guard.as_mut() {
|
||||||
let file = Pin::new(guard.deref_mut());
|
let file = Pin::new(guard.deref_mut());
|
||||||
file.is_write_vectored()
|
file.is_write_vectored()
|
||||||
@@ -742,8 +699,7 @@ impl AsyncRead for WasiStateFileGuard {
|
|||||||
cx: &mut Context<'_>,
|
cx: &mut Context<'_>,
|
||||||
buf: &mut tokio::io::ReadBuf<'_>,
|
buf: &mut tokio::io::ReadBuf<'_>,
|
||||||
) -> Poll<std::io::Result<()>> {
|
) -> Poll<std::io::Result<()>> {
|
||||||
let inodes = self.inodes.read().unwrap();
|
let mut guard = self.lock_write();
|
||||||
let mut guard = self.lock_write(&inodes);
|
|
||||||
if let Some(guard) = guard.as_mut() {
|
if let Some(guard) = guard.as_mut() {
|
||||||
let file = Pin::new(guard.deref_mut());
|
let file = Pin::new(guard.deref_mut());
|
||||||
file.poll_read(cx, buf)
|
file.poll_read(cx, buf)
|
||||||
@@ -752,3 +708,12 @@ impl AsyncRead for WasiStateFileGuard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_err_closed(err: &std::io::Error) -> bool {
|
||||||
|
err.kind() == std::io::ErrorKind::ConnectionAborted
|
||||||
|
|| err.kind() == std::io::ErrorKind::ConnectionRefused
|
||||||
|
|| err.kind() == std::io::ErrorKind::ConnectionReset
|
||||||
|
|| err.kind() == std::io::ErrorKind::BrokenPipe
|
||||||
|
|| err.kind() == std::io::ErrorKind::NotConnected
|
||||||
|
|| err.kind() == std::io::ErrorKind::UnexpectedEof
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -86,6 +86,21 @@ macro_rules! wasi_try_bus_ok {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Like the `try!` macro or `?` syntax: returns the value if the computation
|
||||||
|
/// succeeded or returns the error value.
|
||||||
|
#[allow(unused_macros)]
|
||||||
|
macro_rules! wasi_try_bus_ok_ok {
|
||||||
|
($expr:expr) => {{
|
||||||
|
let res: Result<_, crate::BusErrno> = $expr;
|
||||||
|
match res {
|
||||||
|
Ok(val) => val
|
||||||
|
Err(err) => {
|
||||||
|
return Ok(Err(err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
/// Like `wasi_try` but converts a `MemoryAccessError` to a `wasi::Errno`.
|
/// Like `wasi_try` but converts a `MemoryAccessError` to a `wasi::Errno`.
|
||||||
macro_rules! wasi_try_mem {
|
macro_rules! wasi_try_mem {
|
||||||
($expr:expr) => {{
|
($expr:expr) => {{
|
||||||
@@ -109,6 +124,14 @@ macro_rules! wasi_try_mem_bus_ok {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Like `wasi_try` but converts a `MemoryAccessError` to a __bus_errno_t`.
|
||||||
|
#[allow(unused_macros)]
|
||||||
|
macro_rules! wasi_try_mem_bus_ok_ok {
|
||||||
|
($expr:expr) => {{
|
||||||
|
wasi_try_bus_ok_ok!($expr.map_err($crate::mem_error_to_bus))
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
/// Like `wasi_try` but converts a `MemoryAccessError` to a `wasi::Errno`.
|
/// Like `wasi_try` but converts a `MemoryAccessError` to a `wasi::Errno`.
|
||||||
macro_rules! wasi_try_mem_ok {
|
macro_rules! wasi_try_mem_ok {
|
||||||
($expr:expr) => {{
|
($expr:expr) => {{
|
||||||
@@ -120,6 +143,17 @@ macro_rules! wasi_try_mem_ok {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Like `wasi_try` but converts a `MemoryAccessError` to a `wasi::Errno`.
|
||||||
|
macro_rules! wasi_try_mem_ok_ok {
|
||||||
|
($expr:expr) => {{
|
||||||
|
wasi_try_ok_ok!($expr.map_err($crate::mem_error_to_wasi))
|
||||||
|
}};
|
||||||
|
|
||||||
|
($expr:expr, $thread:expr) => {{
|
||||||
|
wasi_try_ok_ok!($expr.map_err($crate::mem_error_to_wasi), $thread)
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
/// Reads a string from Wasm memory.
|
/// Reads a string from Wasm memory.
|
||||||
macro_rules! get_input_str {
|
macro_rules! get_input_str {
|
||||||
($memory:expr, $data:expr, $len:expr) => {{
|
($memory:expr, $data:expr, $len:expr) => {{
|
||||||
|
|||||||
@@ -386,6 +386,42 @@ pub fn net_error_into_wasi_err(net_error: NetworkError) -> Errno {
|
|||||||
NetworkError::UnexpectedEof => Errno::Proto,
|
NetworkError::UnexpectedEof => Errno::Proto,
|
||||||
NetworkError::WouldBlock => Errno::Again,
|
NetworkError::WouldBlock => Errno::Again,
|
||||||
NetworkError::WriteZero => Errno::Nospc,
|
NetworkError::WriteZero => Errno::Nospc,
|
||||||
|
NetworkError::OsError(code) => match code {
|
||||||
|
libc::EPERM => Errno::Perm,
|
||||||
|
libc::ENOENT => Errno::Noent,
|
||||||
|
libc::ESRCH => Errno::Srch,
|
||||||
|
libc::EINTR => Errno::Intr,
|
||||||
|
libc::EIO => Errno::Io,
|
||||||
|
libc::ENXIO => Errno::Nxio,
|
||||||
|
libc::E2BIG => Errno::Toobig,
|
||||||
|
libc::ENOEXEC => Errno::Noexec,
|
||||||
|
libc::EBADF => Errno::Badf,
|
||||||
|
libc::ECHILD => Errno::Badf,
|
||||||
|
libc::EAGAIN => Errno::Again,
|
||||||
|
libc::ENOMEM => Errno::Badf,
|
||||||
|
libc::EACCES => Errno::Access,
|
||||||
|
libc::EFAULT => Errno::Fault,
|
||||||
|
libc::EBUSY => Errno::Busy,
|
||||||
|
libc::EEXIST => Errno::Exist,
|
||||||
|
libc::EXDEV => Errno::Xdev,
|
||||||
|
libc::ENODEV => Errno::Nodev,
|
||||||
|
libc::ENOTDIR => Errno::Notdir,
|
||||||
|
libc::EISDIR => Errno::Isdir,
|
||||||
|
libc::EINVAL => Errno::Inval,
|
||||||
|
libc::ENFILE => Errno::Nfile,
|
||||||
|
libc::EMFILE => Errno::Mfile,
|
||||||
|
libc::ENOTTY => Errno::Notty,
|
||||||
|
libc::ETXTBSY => Errno::Txtbsy,
|
||||||
|
libc::EFBIG => Errno::Fbig,
|
||||||
|
libc::ENOSPC => Errno::Nospc,
|
||||||
|
libc::ESPIPE => Errno::Spipe,
|
||||||
|
libc::EROFS => Errno::Rofs,
|
||||||
|
libc::EMLINK => Errno::Mlink,
|
||||||
|
libc::EPIPE => Errno::Pipe,
|
||||||
|
libc::EDOM => Errno::Dom,
|
||||||
|
libc::ERANGE => Errno::Range,
|
||||||
|
_ => Errno::Io,
|
||||||
|
},
|
||||||
NetworkError::Unsupported => Errno::Notsup,
|
NetworkError::Unsupported => Errno::Notsup,
|
||||||
NetworkError::UnknownError => Errno::Io,
|
NetworkError::UnknownError => Errno::Io,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,6 @@ pub enum InodeSocketKind {
|
|||||||
socket: Box<dyn VirtualUdpSocket + Sync>,
|
socket: Box<dyn VirtualUdpSocket + Sync>,
|
||||||
peer: Option<SocketAddr>,
|
peer: Option<SocketAddr>,
|
||||||
},
|
},
|
||||||
Closed,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum WasiSocketOption {
|
pub enum WasiSocketOption {
|
||||||
@@ -154,20 +153,39 @@ pub enum TimeType {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
//#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
//#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub(crate) struct InodeSocketInner {
|
pub(crate) struct InodeSocketProtected {
|
||||||
pub kind: InodeSocketKind,
|
pub kind: InodeSocketKind,
|
||||||
|
pub notifications: InodeSocketNotifications,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
//#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
|
pub(crate) struct InodeSocketNotifications {
|
||||||
|
pub closed: bool,
|
||||||
|
pub failed: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
//#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
|
pub(crate) struct InodeSocketInner {
|
||||||
|
pub protected: RwLock<InodeSocketProtected>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
//#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
//#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub struct InodeSocket {
|
pub struct InodeSocket {
|
||||||
pub(crate) inner: Arc<RwLock<InodeSocketInner>>,
|
pub(crate) inner: Arc<InodeSocketInner>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InodeSocket {
|
impl InodeSocket {
|
||||||
pub fn new(kind: InodeSocketKind) -> Self {
|
pub fn new(kind: InodeSocketKind) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: Arc::new(RwLock::new(InodeSocketInner { kind })),
|
inner: Arc::new(InodeSocketInner {
|
||||||
|
protected: RwLock::new(InodeSocketProtected {
|
||||||
|
kind,
|
||||||
|
notifications: Default::default(),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +202,7 @@ impl InodeSocket {
|
|||||||
.unwrap_or(Duration::from_secs(30));
|
.unwrap_or(Duration::from_secs(30));
|
||||||
|
|
||||||
let socket = {
|
let socket = {
|
||||||
let mut inner = self.inner.write().unwrap();
|
let mut inner = self.inner.protected.write().unwrap();
|
||||||
match &mut inner.kind {
|
match &mut inner.kind {
|
||||||
InodeSocketKind::PreSocket {
|
InodeSocketKind::PreSocket {
|
||||||
family,
|
family,
|
||||||
@@ -255,7 +273,7 @@ impl InodeSocket {
|
|||||||
.unwrap_or(Duration::from_secs(30));
|
.unwrap_or(Duration::from_secs(30));
|
||||||
|
|
||||||
let socket = {
|
let socket = {
|
||||||
let inner = self.inner.read().unwrap();
|
let inner = self.inner.protected.read().unwrap();
|
||||||
match &inner.kind {
|
match &inner.kind {
|
||||||
InodeSocketKind::PreSocket {
|
InodeSocketKind::PreSocket {
|
||||||
ty,
|
ty,
|
||||||
@@ -283,10 +301,6 @@ impl InodeSocket {
|
|||||||
return Err(Errno::Notsup);
|
return Err(Errno::Notsup);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
InodeSocketKind::Closed => {
|
|
||||||
tracing::warn!("wasi[?]::sock_listen - failed - socket closed");
|
|
||||||
return Err(Errno::Io);
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
tracing::warn!("wasi[?]::sock_listen - failed - not supported(2)");
|
tracing::warn!("wasi[?]::sock_listen - failed - not supported(2)");
|
||||||
return Err(Errno::Notsup);
|
return Err(Errno::Notsup);
|
||||||
@@ -328,7 +342,7 @@ impl InodeSocket {
|
|||||||
self: Pin<&mut Self>,
|
self: Pin<&mut Self>,
|
||||||
cx: &mut std::task::Context<'_>,
|
cx: &mut std::task::Context<'_>,
|
||||||
) -> std::task::Poll<Self::Output> {
|
) -> std::task::Poll<Self::Output> {
|
||||||
let mut inner = self.sock.inner.write().unwrap();
|
let mut inner = self.sock.inner.protected.write().unwrap();
|
||||||
match &mut inner.kind {
|
match &mut inner.kind {
|
||||||
InodeSocketKind::TcpListener { socket, .. } => {
|
InodeSocketKind::TcpListener { socket, .. } => {
|
||||||
if self.nonblocking {
|
if self.nonblocking {
|
||||||
@@ -342,7 +356,6 @@ impl InodeSocket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
InodeSocketKind::PreSocket { .. } => Poll::Ready(Err(Errno::Notconn)),
|
InodeSocketKind::PreSocket { .. } => Poll::Ready(Err(Errno::Notconn)),
|
||||||
InodeSocketKind::Closed => Poll::Ready(Err(Errno::Io)),
|
|
||||||
_ => Poll::Ready(Err(Errno::Notsup)),
|
_ => Poll::Ready(Err(Errno::Notsup)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -355,7 +368,7 @@ impl InodeSocket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn close(&self) -> Result<(), Errno> {
|
pub fn close(&self) -> Result<(), Errno> {
|
||||||
let mut inner = self.inner.write().unwrap();
|
let mut inner = self.inner.protected.write().unwrap();
|
||||||
match &mut inner.kind {
|
match &mut inner.kind {
|
||||||
InodeSocketKind::TcpListener { .. } => {}
|
InodeSocketKind::TcpListener { .. } => {}
|
||||||
InodeSocketKind::TcpStream { socket, .. } => {
|
InodeSocketKind::TcpStream { socket, .. } => {
|
||||||
@@ -366,7 +379,6 @@ impl InodeSocket {
|
|||||||
InodeSocketKind::WebSocket(_) => {}
|
InodeSocketKind::WebSocket(_) => {}
|
||||||
InodeSocketKind::Raw(_) => {}
|
InodeSocketKind::Raw(_) => {}
|
||||||
InodeSocketKind::PreSocket { .. } => return Err(Errno::Notconn),
|
InodeSocketKind::PreSocket { .. } => return Err(Errno::Notconn),
|
||||||
InodeSocketKind::Closed => return Err(Errno::Notconn),
|
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -380,12 +392,12 @@ impl InodeSocket {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct SocketFlusher<'a> {
|
struct SocketFlusher<'a> {
|
||||||
sock: &'a RwLock<InodeSocketInner>,
|
inner: &'a InodeSocketInner,
|
||||||
}
|
}
|
||||||
impl<'a> Future for SocketFlusher<'a> {
|
impl<'a> Future for SocketFlusher<'a> {
|
||||||
type Output = Result<(), Errno>;
|
type Output = Result<(), Errno>;
|
||||||
fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
|
fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
|
||||||
let mut inner = self.sock.write().unwrap();
|
let mut inner = self.inner.protected.write().unwrap();
|
||||||
match &mut inner.kind {
|
match &mut inner.kind {
|
||||||
InodeSocketKind::TcpListener { .. } => Poll::Ready(Ok(())),
|
InodeSocketKind::TcpListener { .. } => Poll::Ready(Ok(())),
|
||||||
InodeSocketKind::TcpStream { socket, .. } => {
|
InodeSocketKind::TcpStream { socket, .. } => {
|
||||||
@@ -396,13 +408,12 @@ impl InodeSocket {
|
|||||||
InodeSocketKind::WebSocket(_) => Poll::Ready(Ok(())),
|
InodeSocketKind::WebSocket(_) => Poll::Ready(Ok(())),
|
||||||
InodeSocketKind::Raw(_) => Poll::Ready(Ok(())),
|
InodeSocketKind::Raw(_) => Poll::Ready(Ok(())),
|
||||||
InodeSocketKind::PreSocket { .. } => Poll::Ready(Err(Errno::Notconn)),
|
InodeSocketKind::PreSocket { .. } => Poll::Ready(Err(Errno::Notconn)),
|
||||||
InodeSocketKind::Closed => Poll::Ready(Err(Errno::Notconn)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
res = SocketFlusher { sock: &self.inner } => res,
|
res = SocketFlusher { inner: &self.inner } => res,
|
||||||
_ = tasks.sleep_now(timeout) => Err(Errno::Timedout)
|
_ = tasks.sleep_now(timeout) => Err(Errno::Timedout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -420,7 +431,7 @@ impl InodeSocket {
|
|||||||
let timeout = timeout.unwrap_or(Duration::from_secs(30));
|
let timeout = timeout.unwrap_or(Duration::from_secs(30));
|
||||||
|
|
||||||
let connect = {
|
let connect = {
|
||||||
let mut inner = self.inner.write().unwrap();
|
let mut inner = self.inner.protected.write().unwrap();
|
||||||
match &mut inner.kind {
|
match &mut inner.kind {
|
||||||
InodeSocketKind::PreSocket {
|
InodeSocketKind::PreSocket {
|
||||||
ty,
|
ty,
|
||||||
@@ -455,7 +466,6 @@ impl InodeSocket {
|
|||||||
target_peer.replace(peer);
|
target_peer.replace(peer);
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
InodeSocketKind::Closed => return Err(Errno::Io),
|
|
||||||
_ => return Err(Errno::Notsup),
|
_ => return Err(Errno::Notsup),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -472,20 +482,19 @@ impl InodeSocket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn status(&self) -> Result<WasiSocketStatus, Errno> {
|
pub fn status(&self) -> Result<WasiSocketStatus, Errno> {
|
||||||
let inner = self.inner.read().unwrap();
|
let inner = self.inner.protected.read().unwrap();
|
||||||
Ok(match &inner.kind {
|
Ok(match &inner.kind {
|
||||||
InodeSocketKind::PreSocket { .. } => WasiSocketStatus::Opening,
|
InodeSocketKind::PreSocket { .. } => WasiSocketStatus::Opening,
|
||||||
InodeSocketKind::WebSocket(_) => WasiSocketStatus::Opened,
|
InodeSocketKind::WebSocket(_) => WasiSocketStatus::Opened,
|
||||||
InodeSocketKind::TcpListener { .. } => WasiSocketStatus::Opened,
|
InodeSocketKind::TcpListener { .. } => WasiSocketStatus::Opened,
|
||||||
InodeSocketKind::TcpStream { .. } => WasiSocketStatus::Opened,
|
InodeSocketKind::TcpStream { .. } => WasiSocketStatus::Opened,
|
||||||
InodeSocketKind::UdpSocket { .. } => WasiSocketStatus::Opened,
|
InodeSocketKind::UdpSocket { .. } => WasiSocketStatus::Opened,
|
||||||
InodeSocketKind::Closed => WasiSocketStatus::Closed,
|
|
||||||
_ => WasiSocketStatus::Failed,
|
_ => WasiSocketStatus::Failed,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addr_local(&self) -> Result<SocketAddr, Errno> {
|
pub fn addr_local(&self) -> Result<SocketAddr, Errno> {
|
||||||
let inner = self.inner.read().unwrap();
|
let inner = self.inner.protected.read().unwrap();
|
||||||
Ok(match &inner.kind {
|
Ok(match &inner.kind {
|
||||||
InodeSocketKind::PreSocket { family, addr, .. } => {
|
InodeSocketKind::PreSocket { family, addr, .. } => {
|
||||||
if let Some(addr) = addr {
|
if let Some(addr) = addr {
|
||||||
@@ -511,13 +520,12 @@ impl InodeSocket {
|
|||||||
InodeSocketKind::UdpSocket { socket, .. } => {
|
InodeSocketKind::UdpSocket { socket, .. } => {
|
||||||
socket.addr_local().map_err(net_error_into_wasi_err)?
|
socket.addr_local().map_err(net_error_into_wasi_err)?
|
||||||
}
|
}
|
||||||
InodeSocketKind::Closed => return Err(Errno::Io),
|
|
||||||
_ => return Err(Errno::Notsup),
|
_ => return Err(Errno::Notsup),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addr_peer(&self) -> Result<SocketAddr, Errno> {
|
pub fn addr_peer(&self) -> Result<SocketAddr, Errno> {
|
||||||
let inner = self.inner.read().unwrap();
|
let inner = self.inner.protected.read().unwrap();
|
||||||
Ok(match &inner.kind {
|
Ok(match &inner.kind {
|
||||||
InodeSocketKind::PreSocket { family, .. } => SocketAddr::new(
|
InodeSocketKind::PreSocket { family, .. } => SocketAddr::new(
|
||||||
match *family {
|
match *family {
|
||||||
@@ -548,13 +556,12 @@ impl InodeSocket {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
})?,
|
})?,
|
||||||
InodeSocketKind::Closed => return Err(Errno::Io),
|
|
||||||
_ => return Err(Errno::Notsup),
|
_ => return Err(Errno::Notsup),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_opt_flag(&mut self, option: WasiSocketOption, val: bool) -> Result<(), Errno> {
|
pub fn set_opt_flag(&mut self, option: WasiSocketOption, val: bool) -> Result<(), Errno> {
|
||||||
let mut inner = self.inner.write().unwrap();
|
let mut inner = self.inner.protected.write().unwrap();
|
||||||
match &mut inner.kind {
|
match &mut inner.kind {
|
||||||
InodeSocketKind::PreSocket {
|
InodeSocketKind::PreSocket {
|
||||||
only_v6,
|
only_v6,
|
||||||
@@ -593,14 +600,13 @@ impl InodeSocket {
|
|||||||
.map_err(net_error_into_wasi_err)?,
|
.map_err(net_error_into_wasi_err)?,
|
||||||
_ => return Err(Errno::Inval),
|
_ => return Err(Errno::Inval),
|
||||||
},
|
},
|
||||||
InodeSocketKind::Closed => return Err(Errno::Io),
|
|
||||||
_ => return Err(Errno::Notsup),
|
_ => return Err(Errno::Notsup),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_opt_flag(&self, option: WasiSocketOption) -> Result<bool, Errno> {
|
pub fn get_opt_flag(&self, option: WasiSocketOption) -> Result<bool, Errno> {
|
||||||
let mut inner = self.inner.write().unwrap();
|
let mut inner = self.inner.protected.write().unwrap();
|
||||||
Ok(match &mut inner.kind {
|
Ok(match &mut inner.kind {
|
||||||
InodeSocketKind::PreSocket {
|
InodeSocketKind::PreSocket {
|
||||||
only_v6,
|
only_v6,
|
||||||
@@ -635,13 +641,12 @@ impl InodeSocket {
|
|||||||
.map_err(net_error_into_wasi_err)?,
|
.map_err(net_error_into_wasi_err)?,
|
||||||
_ => return Err(Errno::Inval),
|
_ => return Err(Errno::Inval),
|
||||||
},
|
},
|
||||||
InodeSocketKind::Closed => return Err(Errno::Io),
|
|
||||||
_ => return Err(Errno::Notsup),
|
_ => return Err(Errno::Notsup),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_send_buf_size(&mut self, size: usize) -> Result<(), Errno> {
|
pub fn set_send_buf_size(&mut self, size: usize) -> Result<(), Errno> {
|
||||||
let mut inner = self.inner.write().unwrap();
|
let mut inner = self.inner.protected.write().unwrap();
|
||||||
match &mut inner.kind {
|
match &mut inner.kind {
|
||||||
InodeSocketKind::PreSocket { send_buf_size, .. } => {
|
InodeSocketKind::PreSocket { send_buf_size, .. } => {
|
||||||
*send_buf_size = Some(size);
|
*send_buf_size = Some(size);
|
||||||
@@ -651,14 +656,13 @@ impl InodeSocket {
|
|||||||
.set_send_buf_size(size)
|
.set_send_buf_size(size)
|
||||||
.map_err(net_error_into_wasi_err)?;
|
.map_err(net_error_into_wasi_err)?;
|
||||||
}
|
}
|
||||||
InodeSocketKind::Closed => return Err(Errno::Io),
|
|
||||||
_ => return Err(Errno::Notsup),
|
_ => return Err(Errno::Notsup),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_buf_size(&self) -> Result<usize, Errno> {
|
pub fn send_buf_size(&self) -> Result<usize, Errno> {
|
||||||
let inner = self.inner.read().unwrap();
|
let inner = self.inner.protected.read().unwrap();
|
||||||
match &inner.kind {
|
match &inner.kind {
|
||||||
InodeSocketKind::PreSocket { send_buf_size, .. } => {
|
InodeSocketKind::PreSocket { send_buf_size, .. } => {
|
||||||
Ok((*send_buf_size).unwrap_or_default())
|
Ok((*send_buf_size).unwrap_or_default())
|
||||||
@@ -666,13 +670,12 @@ impl InodeSocket {
|
|||||||
InodeSocketKind::TcpStream { socket, .. } => {
|
InodeSocketKind::TcpStream { socket, .. } => {
|
||||||
socket.send_buf_size().map_err(net_error_into_wasi_err)
|
socket.send_buf_size().map_err(net_error_into_wasi_err)
|
||||||
}
|
}
|
||||||
InodeSocketKind::Closed => Err(Errno::Io),
|
|
||||||
_ => Err(Errno::Notsup),
|
_ => Err(Errno::Notsup),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_recv_buf_size(&mut self, size: usize) -> Result<(), Errno> {
|
pub fn set_recv_buf_size(&mut self, size: usize) -> Result<(), Errno> {
|
||||||
let mut inner = self.inner.write().unwrap();
|
let mut inner = self.inner.protected.write().unwrap();
|
||||||
match &mut inner.kind {
|
match &mut inner.kind {
|
||||||
InodeSocketKind::PreSocket { recv_buf_size, .. } => {
|
InodeSocketKind::PreSocket { recv_buf_size, .. } => {
|
||||||
*recv_buf_size = Some(size);
|
*recv_buf_size = Some(size);
|
||||||
@@ -682,14 +685,13 @@ impl InodeSocket {
|
|||||||
.set_recv_buf_size(size)
|
.set_recv_buf_size(size)
|
||||||
.map_err(net_error_into_wasi_err)?;
|
.map_err(net_error_into_wasi_err)?;
|
||||||
}
|
}
|
||||||
InodeSocketKind::Closed => return Err(Errno::Io),
|
|
||||||
_ => return Err(Errno::Notsup),
|
_ => return Err(Errno::Notsup),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recv_buf_size(&self) -> Result<usize, Errno> {
|
pub fn recv_buf_size(&self) -> Result<usize, Errno> {
|
||||||
let inner = self.inner.read().unwrap();
|
let inner = self.inner.protected.read().unwrap();
|
||||||
match &inner.kind {
|
match &inner.kind {
|
||||||
InodeSocketKind::PreSocket { recv_buf_size, .. } => {
|
InodeSocketKind::PreSocket { recv_buf_size, .. } => {
|
||||||
Ok((*recv_buf_size).unwrap_or_default())
|
Ok((*recv_buf_size).unwrap_or_default())
|
||||||
@@ -697,31 +699,28 @@ impl InodeSocket {
|
|||||||
InodeSocketKind::TcpStream { socket, .. } => {
|
InodeSocketKind::TcpStream { socket, .. } => {
|
||||||
socket.recv_buf_size().map_err(net_error_into_wasi_err)
|
socket.recv_buf_size().map_err(net_error_into_wasi_err)
|
||||||
}
|
}
|
||||||
InodeSocketKind::Closed => Err(Errno::Io),
|
|
||||||
_ => Err(Errno::Notsup),
|
_ => Err(Errno::Notsup),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_linger(&mut self, linger: Option<std::time::Duration>) -> Result<(), Errno> {
|
pub fn set_linger(&mut self, linger: Option<std::time::Duration>) -> Result<(), Errno> {
|
||||||
let mut inner = self.inner.write().unwrap();
|
let mut inner = self.inner.protected.write().unwrap();
|
||||||
match &mut inner.kind {
|
match &mut inner.kind {
|
||||||
InodeSocketKind::TcpStream { socket, .. } => {
|
InodeSocketKind::TcpStream { socket, .. } => {
|
||||||
socket.set_linger(linger).map_err(net_error_into_wasi_err)
|
socket.set_linger(linger).map_err(net_error_into_wasi_err)
|
||||||
}
|
}
|
||||||
InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
|
InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
|
||||||
InodeSocketKind::Closed => Err(Errno::Io),
|
|
||||||
_ => Err(Errno::Notsup),
|
_ => Err(Errno::Notsup),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn linger(&self) -> Result<Option<std::time::Duration>, Errno> {
|
pub fn linger(&self) -> Result<Option<std::time::Duration>, Errno> {
|
||||||
let inner = self.inner.read().unwrap();
|
let inner = self.inner.protected.read().unwrap();
|
||||||
match &inner.kind {
|
match &inner.kind {
|
||||||
InodeSocketKind::TcpStream { socket, .. } => {
|
InodeSocketKind::TcpStream { socket, .. } => {
|
||||||
socket.linger().map_err(net_error_into_wasi_err)
|
socket.linger().map_err(net_error_into_wasi_err)
|
||||||
}
|
}
|
||||||
InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
|
InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
|
||||||
InodeSocketKind::Closed => Err(Errno::Io),
|
|
||||||
_ => Err(Errno::Notsup),
|
_ => Err(Errno::Notsup),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -731,7 +730,7 @@ impl InodeSocket {
|
|||||||
ty: TimeType,
|
ty: TimeType,
|
||||||
timeout: Option<std::time::Duration>,
|
timeout: Option<std::time::Duration>,
|
||||||
) -> Result<(), Errno> {
|
) -> Result<(), Errno> {
|
||||||
let mut inner = self.inner.write().unwrap();
|
let mut inner = self.inner.protected.write().unwrap();
|
||||||
match &mut inner.kind {
|
match &mut inner.kind {
|
||||||
InodeSocketKind::TcpStream {
|
InodeSocketKind::TcpStream {
|
||||||
write_timeout,
|
write_timeout,
|
||||||
@@ -768,13 +767,12 @@ impl InodeSocket {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
InodeSocketKind::Closed => Err(Errno::Io),
|
|
||||||
_ => Err(Errno::Notsup),
|
_ => Err(Errno::Notsup),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn opt_time(&self, ty: TimeType) -> Result<Option<std::time::Duration>, Errno> {
|
pub fn opt_time(&self, ty: TimeType) -> Result<Option<std::time::Duration>, Errno> {
|
||||||
let inner = self.inner.read().unwrap();
|
let inner = self.inner.protected.read().unwrap();
|
||||||
match &inner.kind {
|
match &inner.kind {
|
||||||
InodeSocketKind::TcpStream {
|
InodeSocketKind::TcpStream {
|
||||||
read_timeout,
|
read_timeout,
|
||||||
@@ -802,13 +800,12 @@ impl InodeSocket {
|
|||||||
TimeType::WriteTimeout => Ok(*write_timeout),
|
TimeType::WriteTimeout => Ok(*write_timeout),
|
||||||
_ => Err(Errno::Inval),
|
_ => Err(Errno::Inval),
|
||||||
},
|
},
|
||||||
InodeSocketKind::Closed => Err(Errno::Io),
|
|
||||||
_ => Err(Errno::Notsup),
|
_ => Err(Errno::Notsup),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_ttl(&self, ttl: u32) -> Result<(), Errno> {
|
pub fn set_ttl(&self, ttl: u32) -> Result<(), Errno> {
|
||||||
let mut inner = self.inner.write().unwrap();
|
let mut inner = self.inner.protected.write().unwrap();
|
||||||
match &mut inner.kind {
|
match &mut inner.kind {
|
||||||
InodeSocketKind::TcpStream { socket, .. } => {
|
InodeSocketKind::TcpStream { socket, .. } => {
|
||||||
socket.set_ttl(ttl).map_err(net_error_into_wasi_err)
|
socket.set_ttl(ttl).map_err(net_error_into_wasi_err)
|
||||||
@@ -817,13 +814,12 @@ impl InodeSocket {
|
|||||||
socket.set_ttl(ttl).map_err(net_error_into_wasi_err)
|
socket.set_ttl(ttl).map_err(net_error_into_wasi_err)
|
||||||
}
|
}
|
||||||
InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
|
InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
|
||||||
InodeSocketKind::Closed => Err(Errno::Io),
|
|
||||||
_ => Err(Errno::Notsup),
|
_ => Err(Errno::Notsup),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ttl(&self) -> Result<u32, Errno> {
|
pub fn ttl(&self) -> Result<u32, Errno> {
|
||||||
let inner = self.inner.read().unwrap();
|
let inner = self.inner.protected.read().unwrap();
|
||||||
match &inner.kind {
|
match &inner.kind {
|
||||||
InodeSocketKind::TcpStream { socket, .. } => {
|
InodeSocketKind::TcpStream { socket, .. } => {
|
||||||
socket.ttl().map_err(net_error_into_wasi_err)
|
socket.ttl().map_err(net_error_into_wasi_err)
|
||||||
@@ -832,79 +828,72 @@ impl InodeSocket {
|
|||||||
socket.ttl().map_err(net_error_into_wasi_err)
|
socket.ttl().map_err(net_error_into_wasi_err)
|
||||||
}
|
}
|
||||||
InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
|
InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
|
||||||
InodeSocketKind::Closed => Err(Errno::Io),
|
|
||||||
_ => Err(Errno::Notsup),
|
_ => Err(Errno::Notsup),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_multicast_ttl_v4(&self, ttl: u32) -> Result<(), Errno> {
|
pub fn set_multicast_ttl_v4(&self, ttl: u32) -> Result<(), Errno> {
|
||||||
let mut inner = self.inner.write().unwrap();
|
let mut inner = self.inner.protected.write().unwrap();
|
||||||
match &mut inner.kind {
|
match &mut inner.kind {
|
||||||
InodeSocketKind::UdpSocket { socket, .. } => socket
|
InodeSocketKind::UdpSocket { socket, .. } => socket
|
||||||
.set_multicast_ttl_v4(ttl)
|
.set_multicast_ttl_v4(ttl)
|
||||||
.map_err(net_error_into_wasi_err),
|
.map_err(net_error_into_wasi_err),
|
||||||
InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
|
InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
|
||||||
InodeSocketKind::Closed => Err(Errno::Io),
|
|
||||||
_ => Err(Errno::Notsup),
|
_ => Err(Errno::Notsup),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn multicast_ttl_v4(&self) -> Result<u32, Errno> {
|
pub fn multicast_ttl_v4(&self) -> Result<u32, Errno> {
|
||||||
let inner = self.inner.read().unwrap();
|
let inner = self.inner.protected.read().unwrap();
|
||||||
match &inner.kind {
|
match &inner.kind {
|
||||||
InodeSocketKind::UdpSocket { socket, .. } => {
|
InodeSocketKind::UdpSocket { socket, .. } => {
|
||||||
socket.multicast_ttl_v4().map_err(net_error_into_wasi_err)
|
socket.multicast_ttl_v4().map_err(net_error_into_wasi_err)
|
||||||
}
|
}
|
||||||
InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
|
InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
|
||||||
InodeSocketKind::Closed => Err(Errno::Io),
|
|
||||||
_ => Err(Errno::Notsup),
|
_ => Err(Errno::Notsup),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn join_multicast_v4(&self, multiaddr: Ipv4Addr, iface: Ipv4Addr) -> Result<(), Errno> {
|
pub fn join_multicast_v4(&self, multiaddr: Ipv4Addr, iface: Ipv4Addr) -> Result<(), Errno> {
|
||||||
let mut inner = self.inner.write().unwrap();
|
let mut inner = self.inner.protected.write().unwrap();
|
||||||
match &mut inner.kind {
|
match &mut inner.kind {
|
||||||
InodeSocketKind::UdpSocket { socket, .. } => socket
|
InodeSocketKind::UdpSocket { socket, .. } => socket
|
||||||
.join_multicast_v4(multiaddr, iface)
|
.join_multicast_v4(multiaddr, iface)
|
||||||
.map_err(net_error_into_wasi_err),
|
.map_err(net_error_into_wasi_err),
|
||||||
InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
|
InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
|
||||||
InodeSocketKind::Closed => Err(Errno::Io),
|
|
||||||
_ => Err(Errno::Notsup),
|
_ => Err(Errno::Notsup),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn leave_multicast_v4(&self, multiaddr: Ipv4Addr, iface: Ipv4Addr) -> Result<(), Errno> {
|
pub fn leave_multicast_v4(&self, multiaddr: Ipv4Addr, iface: Ipv4Addr) -> Result<(), Errno> {
|
||||||
let mut inner = self.inner.write().unwrap();
|
let mut inner = self.inner.protected.write().unwrap();
|
||||||
match &mut inner.kind {
|
match &mut inner.kind {
|
||||||
InodeSocketKind::UdpSocket { socket, .. } => socket
|
InodeSocketKind::UdpSocket { socket, .. } => socket
|
||||||
.leave_multicast_v4(multiaddr, iface)
|
.leave_multicast_v4(multiaddr, iface)
|
||||||
.map_err(net_error_into_wasi_err),
|
.map_err(net_error_into_wasi_err),
|
||||||
InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
|
InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
|
||||||
InodeSocketKind::Closed => Err(Errno::Io),
|
|
||||||
_ => Err(Errno::Notsup),
|
_ => Err(Errno::Notsup),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn join_multicast_v6(&self, multiaddr: Ipv6Addr, iface: u32) -> Result<(), Errno> {
|
pub fn join_multicast_v6(&self, multiaddr: Ipv6Addr, iface: u32) -> Result<(), Errno> {
|
||||||
let mut inner = self.inner.write().unwrap();
|
let mut inner = self.inner.protected.write().unwrap();
|
||||||
match &mut inner.kind {
|
match &mut inner.kind {
|
||||||
InodeSocketKind::UdpSocket { socket, .. } => socket
|
InodeSocketKind::UdpSocket { socket, .. } => socket
|
||||||
.join_multicast_v6(multiaddr, iface)
|
.join_multicast_v6(multiaddr, iface)
|
||||||
.map_err(net_error_into_wasi_err),
|
.map_err(net_error_into_wasi_err),
|
||||||
InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
|
InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
|
||||||
InodeSocketKind::Closed => Err(Errno::Io),
|
|
||||||
_ => Err(Errno::Notsup),
|
_ => Err(Errno::Notsup),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn leave_multicast_v6(&mut self, multiaddr: Ipv6Addr, iface: u32) -> Result<(), Errno> {
|
pub fn leave_multicast_v6(&mut self, multiaddr: Ipv6Addr, iface: u32) -> Result<(), Errno> {
|
||||||
let mut inner = self.inner.write().unwrap();
|
let mut inner = self.inner.protected.write().unwrap();
|
||||||
match &mut inner.kind {
|
match &mut inner.kind {
|
||||||
InodeSocketKind::UdpSocket { socket, .. } => socket
|
InodeSocketKind::UdpSocket { socket, .. } => socket
|
||||||
.leave_multicast_v6(multiaddr, iface)
|
.leave_multicast_v6(multiaddr, iface)
|
||||||
.map_err(net_error_into_wasi_err),
|
.map_err(net_error_into_wasi_err),
|
||||||
InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
|
InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
|
||||||
InodeSocketKind::Closed => Err(Errno::Io),
|
|
||||||
_ => Err(Errno::Notsup),
|
_ => Err(Errno::Notsup),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -924,14 +913,14 @@ impl InodeSocket {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct SocketSender<'a, 'b> {
|
struct SocketSender<'a, 'b> {
|
||||||
sock: &'a RwLock<InodeSocketInner>,
|
inner: &'a InodeSocketInner,
|
||||||
data: &'b [u8],
|
data: &'b [u8],
|
||||||
nonblocking: bool,
|
nonblocking: bool,
|
||||||
}
|
}
|
||||||
impl<'a, 'b> Future for SocketSender<'a, 'b> {
|
impl<'a, 'b> Future for SocketSender<'a, 'b> {
|
||||||
type Output = Result<usize, Errno>;
|
type Output = Result<usize, Errno>;
|
||||||
fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
|
fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
|
||||||
let mut inner = self.sock.write().unwrap();
|
let mut inner = self.inner.protected.write().unwrap();
|
||||||
match &mut inner.kind {
|
match &mut inner.kind {
|
||||||
InodeSocketKind::WebSocket(sock) => sock
|
InodeSocketKind::WebSocket(sock) => sock
|
||||||
.poll_send(cx, self.data)
|
.poll_send(cx, self.data)
|
||||||
@@ -976,14 +965,13 @@ impl InodeSocket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
InodeSocketKind::PreSocket { .. } => Poll::Ready(Err(Errno::Notconn)),
|
InodeSocketKind::PreSocket { .. } => Poll::Ready(Err(Errno::Notconn)),
|
||||||
InodeSocketKind::Closed => Poll::Ready(Err(Errno::Io)),
|
|
||||||
_ => Poll::Ready(Err(Errno::Notsup)),
|
_ => Poll::Ready(Err(Errno::Notsup)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
res = SocketSender { sock: &self.inner, data: buf, nonblocking } => res,
|
res = SocketSender { inner: &self.inner, data: buf, nonblocking } => res,
|
||||||
_ = tasks.sleep_now(timeout) => Err(Errno::Timedout)
|
_ = tasks.sleep_now(timeout) => Err(Errno::Timedout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1004,7 +992,7 @@ impl InodeSocket {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct SocketSender<'a, 'b> {
|
struct SocketSender<'a, 'b> {
|
||||||
sock: &'a RwLock<InodeSocketInner>,
|
inner: &'a InodeSocketInner,
|
||||||
data: &'b [u8],
|
data: &'b [u8],
|
||||||
addr: SocketAddr,
|
addr: SocketAddr,
|
||||||
nonblocking: bool,
|
nonblocking: bool,
|
||||||
@@ -1012,7 +1000,7 @@ impl InodeSocket {
|
|||||||
impl<'a, 'b> Future for SocketSender<'a, 'b> {
|
impl<'a, 'b> Future for SocketSender<'a, 'b> {
|
||||||
type Output = Result<usize, Errno>;
|
type Output = Result<usize, Errno>;
|
||||||
fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
|
fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
|
||||||
let mut inner = self.sock.write().unwrap();
|
let mut inner = self.inner.protected.write().unwrap();
|
||||||
match &mut inner.kind {
|
match &mut inner.kind {
|
||||||
InodeSocketKind::Icmp(sock) => {
|
InodeSocketKind::Icmp(sock) => {
|
||||||
if self.nonblocking {
|
if self.nonblocking {
|
||||||
@@ -1038,14 +1026,13 @@ impl InodeSocket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
InodeSocketKind::PreSocket { .. } => Poll::Ready(Err(Errno::Notconn)),
|
InodeSocketKind::PreSocket { .. } => Poll::Ready(Err(Errno::Notconn)),
|
||||||
InodeSocketKind::Closed => Poll::Ready(Err(Errno::Io)),
|
|
||||||
_ => Poll::Ready(Err(Errno::Notsup)),
|
_ => Poll::Ready(Err(Errno::Notsup)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
res = SocketSender { sock: &self.inner, data: buf, addr, nonblocking } => res,
|
res = SocketSender { inner: &self.inner, data: buf, addr, nonblocking } => res,
|
||||||
_ = tasks.sleep_now(timeout) => Err(Errno::Timedout)
|
_ = tasks.sleep_now(timeout) => Err(Errno::Timedout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1065,7 +1052,7 @@ impl InodeSocket {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct SocketReceiver<'a, 'b> {
|
struct SocketReceiver<'a, 'b> {
|
||||||
sock: &'a RwLock<InodeSocketInner>,
|
inner: &'a InodeSocketInner,
|
||||||
data: &'b mut [MaybeUninit<u8>],
|
data: &'b mut [MaybeUninit<u8>],
|
||||||
nonblocking: bool,
|
nonblocking: bool,
|
||||||
}
|
}
|
||||||
@@ -1075,7 +1062,7 @@ impl InodeSocket {
|
|||||||
mut self: Pin<&mut Self>,
|
mut self: Pin<&mut Self>,
|
||||||
cx: &mut std::task::Context<'_>,
|
cx: &mut std::task::Context<'_>,
|
||||||
) -> Poll<Self::Output> {
|
) -> Poll<Self::Output> {
|
||||||
let mut inner = self.sock.write().unwrap();
|
let mut inner = self.inner.protected.write().unwrap();
|
||||||
match &mut inner.kind {
|
match &mut inner.kind {
|
||||||
InodeSocketKind::WebSocket(sock) => sock
|
InodeSocketKind::WebSocket(sock) => sock
|
||||||
.poll_recv(cx, self.data)
|
.poll_recv(cx, self.data)
|
||||||
@@ -1132,14 +1119,13 @@ impl InodeSocket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
InodeSocketKind::PreSocket { .. } => Poll::Ready(Err(Errno::Notconn)),
|
InodeSocketKind::PreSocket { .. } => Poll::Ready(Err(Errno::Notconn)),
|
||||||
InodeSocketKind::Closed => Poll::Ready(Err(Errno::Io)),
|
|
||||||
_ => Poll::Ready(Err(Errno::Notsup)),
|
_ => Poll::Ready(Err(Errno::Notsup)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
res = SocketReceiver { sock: &self.inner, data: buf, nonblocking } => res,
|
res = SocketReceiver { inner: &self.inner, data: buf, nonblocking } => res,
|
||||||
_ = tasks.sleep_now(timeout) => Err(Errno::Timedout)
|
_ = tasks.sleep_now(timeout) => Err(Errno::Timedout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1159,7 +1145,7 @@ impl InodeSocket {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct SocketReceiver<'a, 'b> {
|
struct SocketReceiver<'a, 'b> {
|
||||||
sock: &'a RwLock<InodeSocketInner>,
|
inner: &'a InodeSocketInner,
|
||||||
data: &'b mut [MaybeUninit<u8>],
|
data: &'b mut [MaybeUninit<u8>],
|
||||||
nonblocking: bool,
|
nonblocking: bool,
|
||||||
}
|
}
|
||||||
@@ -1169,7 +1155,7 @@ impl InodeSocket {
|
|||||||
mut self: Pin<&mut Self>,
|
mut self: Pin<&mut Self>,
|
||||||
cx: &mut std::task::Context<'_>,
|
cx: &mut std::task::Context<'_>,
|
||||||
) -> Poll<Self::Output> {
|
) -> Poll<Self::Output> {
|
||||||
let mut inner = self.sock.write().unwrap();
|
let mut inner = self.inner.protected.write().unwrap();
|
||||||
match &mut inner.kind {
|
match &mut inner.kind {
|
||||||
InodeSocketKind::Icmp(sock) => {
|
InodeSocketKind::Icmp(sock) => {
|
||||||
if self.nonblocking {
|
if self.nonblocking {
|
||||||
@@ -1195,33 +1181,31 @@ impl InodeSocket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
InodeSocketKind::PreSocket { .. } => Poll::Ready(Err(Errno::Notconn)),
|
InodeSocketKind::PreSocket { .. } => Poll::Ready(Err(Errno::Notconn)),
|
||||||
InodeSocketKind::Closed => Poll::Ready(Err(Errno::Io)),
|
|
||||||
_ => Poll::Ready(Err(Errno::Notsup)),
|
_ => Poll::Ready(Err(Errno::Notsup)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
res = SocketReceiver { sock: &self.inner, data: buf, nonblocking } => res,
|
res = SocketReceiver { inner: &self.inner, data: buf, nonblocking } => res,
|
||||||
_ = tasks.sleep_now(timeout) => Err(Errno::Timedout)
|
_ = tasks.sleep_now(timeout) => Err(Errno::Timedout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shutdown(&mut self, how: std::net::Shutdown) -> Result<(), Errno> {
|
pub fn shutdown(&mut self, how: std::net::Shutdown) -> Result<(), Errno> {
|
||||||
let mut inner = self.inner.write().unwrap();
|
let mut inner = self.inner.protected.write().unwrap();
|
||||||
match &mut inner.kind {
|
match &mut inner.kind {
|
||||||
InodeSocketKind::TcpStream { socket, .. } => {
|
InodeSocketKind::TcpStream { socket, .. } => {
|
||||||
socket.shutdown(how).map_err(net_error_into_wasi_err)?;
|
socket.shutdown(how).map_err(net_error_into_wasi_err)?;
|
||||||
}
|
}
|
||||||
InodeSocketKind::PreSocket { .. } => return Err(Errno::Notconn),
|
InodeSocketKind::PreSocket { .. } => return Err(Errno::Notconn),
|
||||||
InodeSocketKind::Closed => return Err(Errno::Io),
|
|
||||||
_ => return Err(Errno::Notsup),
|
_ => return Err(Errno::Notsup),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn can_write(&self) -> bool {
|
pub async fn can_write(&self) -> bool {
|
||||||
if let Ok(mut guard) = self.inner.try_write() {
|
if let Ok(mut guard) = self.inner.protected.try_write() {
|
||||||
#[allow(clippy::match_like_matches_macro)]
|
#[allow(clippy::match_like_matches_macro)]
|
||||||
match &mut guard.kind {
|
match &mut guard.kind {
|
||||||
InodeSocketKind::TcpStream { .. }
|
InodeSocketKind::TcpStream { .. }
|
||||||
@@ -1236,7 +1220,7 @@ impl InodeSocket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InodeSocketInner {
|
impl InodeSocketProtected {
|
||||||
pub fn poll_read_ready(
|
pub fn poll_read_ready(
|
||||||
&mut self,
|
&mut self,
|
||||||
cx: &mut std::task::Context<'_>,
|
cx: &mut std::task::Context<'_>,
|
||||||
@@ -1251,9 +1235,6 @@ impl InodeSocketInner {
|
|||||||
InodeSocketKind::PreSocket { .. } => {
|
InodeSocketKind::PreSocket { .. } => {
|
||||||
std::task::Poll::Ready(Err(wasmer_vnet::NetworkError::IOError))
|
std::task::Poll::Ready(Err(wasmer_vnet::NetworkError::IOError))
|
||||||
}
|
}
|
||||||
InodeSocketKind::Closed => {
|
|
||||||
std::task::Poll::Ready(Err(wasmer_vnet::NetworkError::ConnectionAborted))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1271,9 +1252,6 @@ impl InodeSocketInner {
|
|||||||
InodeSocketKind::PreSocket { .. } => {
|
InodeSocketKind::PreSocket { .. } => {
|
||||||
std::task::Poll::Ready(Err(wasmer_vnet::NetworkError::IOError))
|
std::task::Poll::Ready(Err(wasmer_vnet::NetworkError::IOError))
|
||||||
}
|
}
|
||||||
InodeSocketKind::Closed => {
|
|
||||||
std::task::Poll::Ready(Err(wasmer_vnet::NetworkError::ConnectionAborted))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ impl CmdWasmer {
|
|||||||
let mut config = config.take().ok_or(VirtualBusError::UnknownError)?.conf();
|
let mut config = config.take().ok_or(VirtualBusError::UnknownError)?.conf();
|
||||||
|
|
||||||
// Set the arguments of the environment by replacing the state
|
// Set the arguments of the environment by replacing the state
|
||||||
let mut state = config.env().state.fork(true);
|
let mut state = config.env().state.fork();
|
||||||
args.insert(0, what.clone());
|
args.insert(0, what.clone());
|
||||||
state.args = args;
|
state.args = args;
|
||||||
config.env_mut().state = Arc::new(state);
|
config.env_mut().state = Arc::new(state);
|
||||||
|
|||||||
@@ -2,12 +2,10 @@
|
|||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
ops::{Deref, DerefMut},
|
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::{Arc, RwLock},
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use generational_arena::Arena;
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use wasmer::AsStoreMut;
|
use wasmer::AsStoreMut;
|
||||||
@@ -49,7 +47,7 @@ pub struct WasiStateBuilder {
|
|||||||
vfs_preopens: Vec<String>,
|
vfs_preopens: Vec<String>,
|
||||||
compiled_modules: Arc<ModuleCache>,
|
compiled_modules: Arc<ModuleCache>,
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
setup_fs_fn: Option<Box<dyn Fn(&mut WasiInodes, &mut WasiFs) -> Result<(), String> + Send>>,
|
setup_fs_fn: Option<Box<dyn Fn(&WasiInodes, &mut WasiFs) -> Result<(), String> + Send>>,
|
||||||
stdout_override: Option<Box<dyn VirtualFile + Send + Sync + 'static>>,
|
stdout_override: Option<Box<dyn VirtualFile + Send + Sync + 'static>>,
|
||||||
stderr_override: Option<Box<dyn VirtualFile + Send + Sync + 'static>>,
|
stderr_override: Option<Box<dyn VirtualFile + Send + Sync + 'static>>,
|
||||||
stdin_override: Option<Box<dyn VirtualFile + Send + Sync + 'static>>,
|
stdin_override: Option<Box<dyn VirtualFile + Send + Sync + 'static>>,
|
||||||
@@ -109,7 +107,7 @@ fn validate_mapped_dir_alias(alias: &str) -> Result<(), WasiStateCreationError>
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type SetupFsFn = Box<dyn Fn(&mut WasiInodes, &mut WasiFs) -> Result<(), String> + Send>;
|
pub type SetupFsFn = Box<dyn Fn(&WasiInodes, &mut WasiFs) -> Result<(), String> + Send>;
|
||||||
|
|
||||||
// TODO add other WasiFS APIs here like swapping out stdout, for example (though we need to
|
// TODO add other WasiFS APIs here like swapping out stdout, for example (though we need to
|
||||||
// return stdout somehow, it's unclear what that API should look like)
|
// return stdout somehow, it's unclear what that API should look like)
|
||||||
@@ -510,46 +508,35 @@ impl WasiStateBuilder {
|
|||||||
.unwrap_or_else(|| WasiFsRoot::Sandbox(Arc::new(TmpFileSystem::new())));
|
.unwrap_or_else(|| WasiFsRoot::Sandbox(Arc::new(TmpFileSystem::new())));
|
||||||
|
|
||||||
// self.preopens are checked in [`PreopenDirBuilder::build`]
|
// self.preopens are checked in [`PreopenDirBuilder::build`]
|
||||||
let inodes = RwLock::new(crate::state::WasiInodes {
|
let inodes = crate::state::WasiInodes::new();
|
||||||
arena: Arena::new(),
|
|
||||||
orphan_fds: HashMap::new(),
|
|
||||||
});
|
|
||||||
let wasi_fs = {
|
let wasi_fs = {
|
||||||
let mut inodes = inodes.write().unwrap();
|
|
||||||
|
|
||||||
// self.preopens are checked in [`PreopenDirBuilder::build`]
|
// self.preopens are checked in [`PreopenDirBuilder::build`]
|
||||||
let mut wasi_fs = WasiFs::new_with_preopen(
|
let mut wasi_fs =
|
||||||
inodes.deref_mut(),
|
WasiFs::new_with_preopen(&inodes, &self.preopens, &self.vfs_preopens, fs_backing)
|
||||||
&self.preopens,
|
.map_err(WasiStateCreationError::WasiFsCreationError)?;
|
||||||
&self.vfs_preopens,
|
|
||||||
fs_backing,
|
|
||||||
)
|
|
||||||
.map_err(WasiStateCreationError::WasiFsCreationError)?;
|
|
||||||
|
|
||||||
// set up the file system, overriding base files and calling the setup function
|
// set up the file system, overriding base files and calling the setup function
|
||||||
wasi_fs
|
wasi_fs
|
||||||
.swap_file(inodes.deref(), __WASI_STDIN_FILENO, stdin)
|
.swap_file(__WASI_STDIN_FILENO, stdin)
|
||||||
.map_err(WasiStateCreationError::FileSystemError)?;
|
.map_err(WasiStateCreationError::FileSystemError)?;
|
||||||
|
|
||||||
if let Some(stdout_override) = self.stdout_override.take() {
|
if let Some(stdout_override) = self.stdout_override.take() {
|
||||||
wasi_fs
|
wasi_fs
|
||||||
.swap_file(inodes.deref(), __WASI_STDOUT_FILENO, stdout_override)
|
.swap_file(__WASI_STDOUT_FILENO, stdout_override)
|
||||||
.map_err(WasiStateCreationError::FileSystemError)?;
|
.map_err(WasiStateCreationError::FileSystemError)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(stderr_override) = self.stderr_override.take() {
|
if let Some(stderr_override) = self.stderr_override.take() {
|
||||||
wasi_fs
|
wasi_fs
|
||||||
.swap_file(inodes.deref(), __WASI_STDERR_FILENO, stderr_override)
|
.swap_file(__WASI_STDERR_FILENO, stderr_override)
|
||||||
.map_err(WasiStateCreationError::FileSystemError)?;
|
.map_err(WasiStateCreationError::FileSystemError)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(f) = &self.setup_fs_fn {
|
if let Some(f) = &self.setup_fs_fn {
|
||||||
f(inodes.deref_mut(), &mut wasi_fs)
|
f(&inodes, &mut wasi_fs).map_err(WasiStateCreationError::WasiFsSetupError)?;
|
||||||
.map_err(WasiStateCreationError::WasiFsSetupError)?;
|
|
||||||
}
|
}
|
||||||
wasi_fs
|
wasi_fs
|
||||||
};
|
};
|
||||||
let inodes = Arc::new(inodes);
|
|
||||||
|
|
||||||
Ok(WasiState {
|
Ok(WasiState {
|
||||||
fs: wasi_fs,
|
fs: wasi_fs,
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
use std::{
|
use std::{ops::Deref, sync::Arc};
|
||||||
ops::Deref,
|
|
||||||
sync::{Arc, RwLockReadGuard, RwLockWriteGuard},
|
|
||||||
};
|
|
||||||
|
|
||||||
use derivative::Derivative;
|
use derivative::Derivative;
|
||||||
use tracing::{trace, warn};
|
use tracing::{trace, warn};
|
||||||
@@ -200,6 +197,8 @@ pub struct WasiEnv {
|
|||||||
pub stack_base: u64,
|
pub stack_base: u64,
|
||||||
/// Start of the stack memory that is allocated for this thread
|
/// Start of the stack memory that is allocated for this thread
|
||||||
pub stack_start: u64,
|
pub stack_start: u64,
|
||||||
|
/// Seed used to rotate around the events returned by `poll_oneoff`
|
||||||
|
pub poll_seed: u64,
|
||||||
/// Shared state of the WASI system. Manages all the data that the
|
/// Shared state of the WASI system. Manages all the data that the
|
||||||
/// executing WASI program can see.
|
/// executing WASI program can see.
|
||||||
pub state: Arc<WasiState>,
|
pub state: Arc<WasiState>,
|
||||||
@@ -234,7 +233,7 @@ impl WasiEnv {
|
|||||||
let thread = handle.as_thread();
|
let thread = handle.as_thread();
|
||||||
thread.copy_stack_from(&self.thread);
|
thread.copy_stack_from(&self.thread);
|
||||||
|
|
||||||
let state = Arc::new(self.state.fork(true));
|
let state = Arc::new(self.state.fork());
|
||||||
|
|
||||||
let bin_factory = {
|
let bin_factory = {
|
||||||
let mut bin_factory = self.bin_factory.clone();
|
let mut bin_factory = self.bin_factory.clone();
|
||||||
@@ -246,6 +245,7 @@ impl WasiEnv {
|
|||||||
process,
|
process,
|
||||||
thread,
|
thread,
|
||||||
vfork: None,
|
vfork: None,
|
||||||
|
poll_seed: 0,
|
||||||
stack_base: self.stack_base,
|
stack_base: self.stack_base,
|
||||||
stack_start: self.stack_start,
|
stack_start: self.stack_start,
|
||||||
bin_factory,
|
bin_factory,
|
||||||
@@ -293,6 +293,7 @@ impl WasiEnv {
|
|||||||
process,
|
process,
|
||||||
thread: thread.as_thread(),
|
thread: thread.as_thread(),
|
||||||
vfork: None,
|
vfork: None,
|
||||||
|
poll_seed: 0,
|
||||||
stack_base: DEFAULT_STACK_SIZE,
|
stack_base: DEFAULT_STACK_SIZE,
|
||||||
stack_start: 0,
|
stack_start: 0,
|
||||||
state,
|
state,
|
||||||
@@ -529,21 +530,10 @@ impl WasiEnv {
|
|||||||
&'a self,
|
&'a self,
|
||||||
store: &'a impl AsStoreRef,
|
store: &'a impl AsStoreRef,
|
||||||
_mem_index: u32,
|
_mem_index: u32,
|
||||||
) -> (MemoryView<'a>, &WasiState, RwLockReadGuard<WasiInodes>) {
|
) -> (MemoryView<'a>, &WasiState, &WasiInodes) {
|
||||||
let memory = self.memory_view(store);
|
let memory = self.memory_view(store);
|
||||||
let state = self.state.deref();
|
let state = self.state.deref();
|
||||||
let inodes = state.inodes.read().unwrap();
|
let inodes = &state.inodes;
|
||||||
(memory, state, inodes)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn get_memory_and_wasi_state_and_inodes_mut<'a>(
|
|
||||||
&'a self,
|
|
||||||
store: &'a impl AsStoreRef,
|
|
||||||
_mem_index: u32,
|
|
||||||
) -> (MemoryView<'a>, &WasiState, RwLockWriteGuard<WasiInodes>) {
|
|
||||||
let memory = self.memory_view(store);
|
|
||||||
let state = self.state.deref();
|
|
||||||
let inodes = state.inodes.write().unwrap();
|
|
||||||
(memory, state, inodes)
|
(memory, state, inodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -693,9 +683,7 @@ impl WasiEnv {
|
|||||||
// If this is the main thread then also close all the files
|
// If this is the main thread then also close all the files
|
||||||
if self.thread.is_main() {
|
if self.thread.is_main() {
|
||||||
trace!("wasi[{}]:: cleaning up open file handles", self.pid());
|
trace!("wasi[{}]:: cleaning up open file handles", self.pid());
|
||||||
|
self.state.fs.close_all();
|
||||||
let inodes = self.state.inodes.read().unwrap();
|
|
||||||
self.state.fs.close_all(inodes.deref());
|
|
||||||
|
|
||||||
// Now send a signal that the thread is terminated
|
// Now send a signal that the thread is terminated
|
||||||
self.process.signal_process(Signal::Sigquit);
|
self.process.signal_process(Signal::Sigquit);
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use derivative::Derivative;
|
use derivative::Derivative;
|
||||||
pub use generational_arena::Index as Inode;
|
|
||||||
#[cfg(feature = "enable-serde")]
|
#[cfg(feature = "enable-serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use wasmer::Store;
|
use wasmer::Store;
|
||||||
@@ -46,6 +45,7 @@ pub use self::{
|
|||||||
func_env::WasiFunctionEnv,
|
func_env::WasiFunctionEnv,
|
||||||
types::*,
|
types::*,
|
||||||
};
|
};
|
||||||
|
pub use crate::fs::{InodeGuard, InodeWeakGuard};
|
||||||
use crate::{
|
use crate::{
|
||||||
fs::{fs_error_into_wasi_err, WasiFs, WasiFsRoot, WasiInodes, WasiStateFileGuard},
|
fs::{fs_error_into_wasi_err, WasiFs, WasiFsRoot, WasiInodes, WasiStateFileGuard},
|
||||||
os::task::process::WasiProcessId,
|
os::task::process::WasiProcessId,
|
||||||
@@ -243,7 +243,7 @@ impl WasiBusState {
|
|||||||
pub struct WasiState {
|
pub struct WasiState {
|
||||||
pub fs: WasiFs,
|
pub fs: WasiFs,
|
||||||
pub secret: [u8; 32],
|
pub secret: [u8; 32],
|
||||||
pub inodes: Arc<RwLock<WasiInodes>>,
|
pub inodes: WasiInodes,
|
||||||
// TODO: review allow...
|
// TODO: review allow...
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) threading: RwLock<WasiStateThreading>,
|
pub(crate) threading: RwLock<WasiStateThreading>,
|
||||||
@@ -343,9 +343,9 @@ impl WasiState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Forking the WasiState is used when either fork or vfork is called
|
/// Forking the WasiState is used when either fork or vfork is called
|
||||||
pub fn fork(&self, inc_refs: bool) -> Self {
|
pub fn fork(&self) -> Self {
|
||||||
WasiState {
|
WasiState {
|
||||||
fs: self.fs.fork(inc_refs),
|
fs: self.fs.fork(),
|
||||||
secret: self.secret,
|
secret: self.secret,
|
||||||
inodes: self.inodes.clone(),
|
inodes: self.inodes.clone(),
|
||||||
threading: Default::default(),
|
threading: Default::default(),
|
||||||
|
|||||||
@@ -105,8 +105,9 @@ pub(crate) use crate::{
|
|||||||
},
|
},
|
||||||
runtime::{task_manager::VirtualTaskManagerExt, SpawnType},
|
runtime::{task_manager::VirtualTaskManagerExt, SpawnType},
|
||||||
state::{
|
state::{
|
||||||
self, bus_errno_into_vbus_error, iterate_poll_events, vbus_error_into_bus_errno, Inode,
|
self, bus_errno_into_vbus_error, iterate_poll_events, vbus_error_into_bus_errno,
|
||||||
PollEvent, PollEventBuilder, WasiBusCall, WasiFutex, WasiState, WasiThreadContext,
|
InodeGuard, InodeWeakGuard, PollEvent, PollEventBuilder, WasiBusCall, WasiFutex, WasiState,
|
||||||
|
WasiThreadContext,
|
||||||
},
|
},
|
||||||
utils::{self, map_io_err},
|
utils::{self, map_io_err},
|
||||||
VirtualTaskManager, WasiEnv, WasiEnvInner, WasiError, WasiFunctionEnv,
|
VirtualTaskManager, WasiEnv, WasiEnvInner, WasiError, WasiFunctionEnv,
|
||||||
@@ -118,6 +119,7 @@ use crate::{
|
|||||||
MAX_SYMLINKS,
|
MAX_SYMLINKS,
|
||||||
},
|
},
|
||||||
utils::store::InstanceSnapshot,
|
utils::store::InstanceSnapshot,
|
||||||
|
WasiInodes,
|
||||||
};
|
};
|
||||||
pub(crate) use crate::{net::net_error_into_wasi_err, utils::WasiParkingLot};
|
pub(crate) use crate::{net::net_error_into_wasi_err, utils::WasiParkingLot};
|
||||||
|
|
||||||
@@ -248,11 +250,9 @@ pub(crate) fn read_bytes<T: Read, M: MemorySize>(
|
|||||||
|
|
||||||
pub async fn stderr_write(ctx: &FunctionEnvMut<'_, WasiEnv>, buf: &[u8]) -> Result<(), Errno> {
|
pub async fn stderr_write(ctx: &FunctionEnvMut<'_, WasiEnv>, buf: &[u8]) -> Result<(), Errno> {
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (memory, state, inodes) = env.get_memory_and_wasi_state_and_inodes_mut(ctx, 0);
|
let (memory, state, inodes) = env.get_memory_and_wasi_state_and_inodes(ctx, 0);
|
||||||
|
|
||||||
let mut stderr = inodes
|
let mut stderr = WasiInodes::stderr_mut(&state.fs.fd_map).map_err(fs_error_into_wasi_err)?;
|
||||||
.stderr_mut(&state.fs.fd_map)
|
|
||||||
.map_err(fs_error_into_wasi_err)?;
|
|
||||||
|
|
||||||
stderr.write_all(buf).await.map_err(map_io_err)
|
stderr.write_all(buf).await.map_err(map_io_err)
|
||||||
}
|
}
|
||||||
@@ -465,19 +465,13 @@ where
|
|||||||
F: FnOnce(crate::net::socket::InodeSocket, Fd) -> Fut,
|
F: FnOnce(crate::net::socket::InodeSocket, Fd) -> Fut,
|
||||||
Fut: std::future::Future<Output = Result<T, Errno>>,
|
Fut: std::future::Future<Output = Result<T, Errno>>,
|
||||||
{
|
{
|
||||||
let state = env.state.clone();
|
let fd_entry = env.state.fs.get_fd(sock)?;
|
||||||
let inodes = state.inodes.clone();
|
|
||||||
|
|
||||||
let fd_entry = state.fs.get_fd(sock)?;
|
|
||||||
if !rights.is_empty() && !fd_entry.rights.contains(rights) {
|
if !rights.is_empty() && !fd_entry.rights.contains(rights) {
|
||||||
return Err(Errno::Access);
|
return Err(Errno::Access);
|
||||||
}
|
}
|
||||||
|
|
||||||
let work = {
|
let work = {
|
||||||
let inodes_guard = inodes.read().unwrap();
|
let inode = fd_entry.inode.clone();
|
||||||
let inode_idx = fd_entry.inode;
|
|
||||||
let inode = &inodes_guard.arena[inode_idx];
|
|
||||||
|
|
||||||
let tasks = env.tasks.clone();
|
let tasks = env.tasks.clone();
|
||||||
let mut guard = inode.read();
|
let mut guard = inode.read();
|
||||||
match guard.deref() {
|
match guard.deref() {
|
||||||
@@ -514,24 +508,18 @@ where
|
|||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let tasks = env.tasks.clone();
|
let tasks = env.tasks.clone();
|
||||||
|
|
||||||
let state = env.state.clone();
|
let fd_entry = env.state.fs.get_fd(sock)?;
|
||||||
let inodes = state.inodes.clone();
|
|
||||||
|
|
||||||
let fd_entry = state.fs.get_fd(sock)?;
|
|
||||||
if !rights.is_empty() && !fd_entry.rights.contains(rights) {
|
if !rights.is_empty() && !fd_entry.rights.contains(rights) {
|
||||||
return Err(Errno::Access);
|
return Err(Errno::Access);
|
||||||
}
|
}
|
||||||
|
|
||||||
let inode_idx = fd_entry.inode;
|
let inode = fd_entry.inode.clone();
|
||||||
let inodes_guard = inodes.read().unwrap();
|
|
||||||
let inode = &inodes_guard.arena[inode_idx];
|
|
||||||
let mut guard = inode.write();
|
let mut guard = inode.write();
|
||||||
match guard.deref_mut() {
|
match guard.deref_mut() {
|
||||||
Kind::Socket { socket } => {
|
Kind::Socket { socket } => {
|
||||||
// Clone the socket and release the lock
|
// Clone the socket and release the lock
|
||||||
let socket = socket.clone();
|
let socket = socket.clone();
|
||||||
drop(guard);
|
drop(guard);
|
||||||
drop(inodes_guard);
|
|
||||||
|
|
||||||
// Start the work using the socket
|
// Start the work using the socket
|
||||||
let work = actor(socket, fd_entry);
|
let work = actor(socket, fd_entry);
|
||||||
@@ -558,17 +546,12 @@ where
|
|||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let tasks = env.tasks.clone();
|
let tasks = env.tasks.clone();
|
||||||
|
|
||||||
let state = env.state.clone();
|
let fd_entry = env.state.fs.get_fd(sock)?;
|
||||||
let inodes = state.inodes.clone();
|
|
||||||
|
|
||||||
let fd_entry = state.fs.get_fd(sock)?;
|
|
||||||
if !rights.is_empty() && !fd_entry.rights.contains(rights) {
|
if !rights.is_empty() && !fd_entry.rights.contains(rights) {
|
||||||
return Err(Errno::Access);
|
return Err(Errno::Access);
|
||||||
}
|
}
|
||||||
|
|
||||||
let inodes_guard = inodes.read().unwrap();
|
let inode = fd_entry.inode.clone();
|
||||||
let inode_idx = fd_entry.inode;
|
|
||||||
let inode = &inodes_guard.arena[inode_idx];
|
|
||||||
|
|
||||||
let tasks = env.tasks.clone();
|
let tasks = env.tasks.clone();
|
||||||
let mut guard = inode.read();
|
let mut guard = inode.read();
|
||||||
@@ -602,24 +585,18 @@ where
|
|||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let tasks = env.tasks.clone();
|
let tasks = env.tasks.clone();
|
||||||
|
|
||||||
let state = env.state.clone();
|
let fd_entry = env.state.fs.get_fd(sock)?;
|
||||||
let inodes = state.inodes.clone();
|
|
||||||
|
|
||||||
let fd_entry = state.fs.get_fd(sock)?;
|
|
||||||
if !rights.is_empty() && !fd_entry.rights.contains(rights) {
|
if !rights.is_empty() && !fd_entry.rights.contains(rights) {
|
||||||
return Err(Errno::Access);
|
return Err(Errno::Access);
|
||||||
}
|
}
|
||||||
|
|
||||||
let inode_idx = fd_entry.inode;
|
let inode = fd_entry.inode.clone();
|
||||||
let inodes_guard = inodes.read().unwrap();
|
|
||||||
let inode = &inodes_guard.arena[inode_idx];
|
|
||||||
let mut guard = inode.write();
|
let mut guard = inode.write();
|
||||||
match guard.deref_mut() {
|
match guard.deref_mut() {
|
||||||
Kind::Socket { socket } => {
|
Kind::Socket { socket } => {
|
||||||
// Clone the socket and release the lock
|
// Clone the socket and release the lock
|
||||||
let socket = socket.clone();
|
let socket = socket.clone();
|
||||||
drop(guard);
|
drop(guard);
|
||||||
drop(inodes_guard);
|
|
||||||
|
|
||||||
// Start the work using the socket
|
// Start the work using the socket
|
||||||
actor(socket, fd_entry)
|
actor(socket, fd_entry)
|
||||||
@@ -642,10 +619,7 @@ where
|
|||||||
Fut: std::future::Future<Output = Result<Option<crate::net::socket::InodeSocket>, Errno>> + 'a,
|
Fut: std::future::Future<Output = Result<Option<crate::net::socket::InodeSocket>, Errno>> + 'a,
|
||||||
{
|
{
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let state = env.state.clone();
|
let fd_entry = env.state.fs.get_fd(sock)?;
|
||||||
let inodes = state.inodes.clone();
|
|
||||||
|
|
||||||
let fd_entry = state.fs.get_fd(sock)?;
|
|
||||||
if !rights.is_empty() && !fd_entry.rights.contains(rights) {
|
if !rights.is_empty() && !fd_entry.rights.contains(rights) {
|
||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
"wasi[{}:{}]::sock_upgrade(fd={}, rights={:?}) - failed - no access rights to upgrade",
|
"wasi[{}:{}]::sock_upgrade(fd={}, rights={:?}) - failed - no access rights to upgrade",
|
||||||
@@ -659,15 +633,12 @@ where
|
|||||||
|
|
||||||
let tasks = env.tasks.clone();
|
let tasks = env.tasks.clone();
|
||||||
{
|
{
|
||||||
let inode_idx = fd_entry.inode;
|
let inode = fd_entry.inode.clone();
|
||||||
let inodes_guard = inodes.read().unwrap();
|
|
||||||
let inode = &inodes_guard.arena[inode_idx];
|
|
||||||
let mut guard = inode.write();
|
let mut guard = inode.write();
|
||||||
match guard.deref_mut() {
|
match guard.deref_mut() {
|
||||||
Kind::Socket { socket } => {
|
Kind::Socket { socket } => {
|
||||||
let socket = socket.clone();
|
let socket = socket.clone();
|
||||||
drop(guard);
|
drop(guard);
|
||||||
drop(inodes_guard);
|
|
||||||
|
|
||||||
// Start the work using the socket
|
// Start the work using the socket
|
||||||
let work = actor(socket);
|
let work = actor(socket);
|
||||||
@@ -681,8 +652,6 @@ where
|
|||||||
let new_socket = rx.recv().unwrap()?;
|
let new_socket = rx.recv().unwrap()?;
|
||||||
|
|
||||||
if let Some(mut new_socket) = new_socket {
|
if let Some(mut new_socket) = new_socket {
|
||||||
let inodes_guard = inodes.read().unwrap();
|
|
||||||
let inode = &inodes_guard.arena[inode_idx];
|
|
||||||
let mut guard = inode.write();
|
let mut guard = inode.write();
|
||||||
match guard.deref_mut() {
|
match guard.deref_mut() {
|
||||||
Kind::Socket { socket } => {
|
Kind::Socket { socket } => {
|
||||||
@@ -1096,7 +1065,7 @@ pub(crate) fn handle_rewind<M: MemorySize>(ctx: &mut FunctionEnvMut<'_, WasiEnv>
|
|||||||
pub(crate) fn _prepare_wasi(wasi_env: &mut WasiEnv, args: Option<Vec<String>>) {
|
pub(crate) fn _prepare_wasi(wasi_env: &mut WasiEnv, args: Option<Vec<String>>) {
|
||||||
// Swap out the arguments with the new ones
|
// Swap out the arguments with the new ones
|
||||||
if let Some(args) = args {
|
if let Some(args) = args {
|
||||||
let mut wasi_state = wasi_env.state.fork(false);
|
let mut wasi_state = wasi_env.state.fork();
|
||||||
wasi_state.args = args;
|
wasi_state.args = args;
|
||||||
wasi_env.state = Arc::new(wasi_state);
|
wasi_env.state = Arc::new(wasi_state);
|
||||||
}
|
}
|
||||||
@@ -1120,8 +1089,7 @@ pub(crate) fn _prepare_wasi(wasi_env: &mut WasiEnv, args: Option<Vec<String>>) {
|
|||||||
|
|
||||||
// Now close all these files
|
// Now close all these files
|
||||||
for fd in close_fds {
|
for fd in close_fds {
|
||||||
let inodes = wasi_env.state.inodes.read().unwrap();
|
let _ = wasi_env.state.fs.close_fd(fd);
|
||||||
let _ = wasi_env.state.fs.close_fd(inodes.deref(), fd);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ pub fn fd_allocate(
|
|||||||
ctx.data().tid()
|
ctx.data().tid()
|
||||||
);
|
);
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
let (_, mut state) = env.get_memory_and_wasi_state(&ctx, 0);
|
||||||
let fd_entry = wasi_try!(state.fs.get_fd(fd));
|
let fd_entry = wasi_try!(state.fs.get_fd(fd));
|
||||||
let inode = fd_entry.inode;
|
let inode = fd_entry.inode;
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ pub fn fd_allocate(
|
|||||||
}
|
}
|
||||||
let new_size = wasi_try!(offset.checked_add(len).ok_or(Errno::Inval));
|
let new_size = wasi_try!(offset.checked_add(len).ok_or(Errno::Inval));
|
||||||
{
|
{
|
||||||
let mut guard = inodes.arena[inode].write();
|
let mut guard = inode.write();
|
||||||
match guard.deref_mut() {
|
match guard.deref_mut() {
|
||||||
Kind::File { handle, .. } => {
|
Kind::File { handle, .. } => {
|
||||||
if let Some(handle) = handle {
|
if let Some(handle) = handle {
|
||||||
@@ -51,7 +51,7 @@ pub fn fd_allocate(
|
|||||||
Kind::Dir { .. } | Kind::Root { .. } => return Errno::Isdir,
|
Kind::Dir { .. } | Kind::Root { .. } => return Errno::Isdir,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inodes.arena[inode].stat.write().unwrap().st_size = new_size;
|
inode.stat.write().unwrap().st_size = new_size;
|
||||||
debug!("New file size: {}", new_size);
|
debug!("New file size: {}", new_size);
|
||||||
|
|
||||||
Errno::Success
|
Errno::Success
|
||||||
|
|||||||
@@ -19,37 +19,10 @@ pub fn fd_close(mut ctx: FunctionEnvMut<'_, WasiEnv>, fd: WasiFd) -> Result<Errn
|
|||||||
ctx.data().tid(),
|
ctx.data().tid(),
|
||||||
fd
|
fd
|
||||||
);
|
);
|
||||||
let ret = {
|
|
||||||
let env = ctx.data();
|
|
||||||
let (mut memory, _, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
|
||||||
let fd_entry = wasi_try_ok!(env.state.fs.get_fd(fd));
|
|
||||||
|
|
||||||
let is_non_blocking = fd_entry.flags.contains(Fdflags::NONBLOCK);
|
|
||||||
let inode_idx = fd_entry.inode;
|
|
||||||
|
|
||||||
if let Some(inode) = inodes.arena.get(inode_idx) {
|
|
||||||
let mut guard = inode.write();
|
|
||||||
match guard.deref_mut() {
|
|
||||||
Kind::Socket { socket } => {
|
|
||||||
let socket = socket.clone();
|
|
||||||
drop(guard);
|
|
||||||
drop(inodes);
|
|
||||||
|
|
||||||
__asyncify(&mut ctx, None, async move {
|
|
||||||
socket.close().map(|()| Errno::Success)
|
|
||||||
})?
|
|
||||||
.unwrap_or_else(|a| a)
|
|
||||||
}
|
|
||||||
_ => Errno::Success,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Ok(Errno::Success);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
let (_, mut state) = env.get_memory_and_wasi_state(&ctx, 0);
|
||||||
wasi_try_ok!(state.fs.close_fd(inodes.deref(), fd));
|
wasi_try_ok!(state.fs.close_fd(fd));
|
||||||
|
|
||||||
Ok(ret)
|
Ok(Errno::Success)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,18 +14,12 @@ pub fn fd_datasync(mut ctx: FunctionEnvMut<'_, WasiEnv>, fd: WasiFd) -> Result<E
|
|||||||
);
|
);
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let state = env.state.clone();
|
let state = env.state.clone();
|
||||||
let inodes = state.inodes.clone();
|
|
||||||
let fd_entry = wasi_try_ok!(state.fs.get_fd(fd));
|
let fd_entry = wasi_try_ok!(state.fs.get_fd(fd));
|
||||||
if !fd_entry.rights.contains(Rights::FD_DATASYNC) {
|
if !fd_entry.rights.contains(Rights::FD_DATASYNC) {
|
||||||
return Ok(Errno::Access);
|
return Ok(Errno::Access);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(wasi_try_ok!(__asyncify(&mut ctx, None, async move {
|
Ok(wasi_try_ok!(__asyncify(&mut ctx, None, async move {
|
||||||
let inodes = inodes.read().unwrap();
|
state.fs.flush(fd).await.map(|_| Errno::Success)
|
||||||
state
|
|
||||||
.fs
|
|
||||||
.flush(inodes.deref(), fd)
|
|
||||||
.await
|
|
||||||
.map(|_| Errno::Success)
|
|
||||||
})?))
|
})?))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::syscalls::*;
|
use crate::{fs::NotificationInner, syscalls::*};
|
||||||
|
|
||||||
/// ### `fd_event()`
|
/// ### `fd_event()`
|
||||||
/// Creates a file handle for event notifications
|
/// Creates a file handle for event notifications
|
||||||
@@ -12,17 +12,17 @@ pub fn fd_event<M: MemorySize>(
|
|||||||
debug!("wasi[{}:{}]::fd_event", ctx.data().pid(), ctx.data().tid());
|
debug!("wasi[{}:{}]::fd_event", ctx.data().pid(), ctx.data().tid());
|
||||||
|
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0);
|
let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
||||||
|
|
||||||
let kind = Kind::EventNotifications {
|
let kind = Kind::EventNotifications(Arc::new(NotificationInner {
|
||||||
counter: Arc::new(AtomicU64::new(initial_val)),
|
counter: AtomicU64::new(initial_val),
|
||||||
|
last_poll: AtomicU64::new(0),
|
||||||
is_semaphore: flags & EVENT_FD_FLAGS_SEMAPHORE != 0,
|
is_semaphore: flags & EVENT_FD_FLAGS_SEMAPHORE != 0,
|
||||||
wakers: Default::default(),
|
wakers: Default::default(),
|
||||||
immediate: Arc::new(AtomicBool::new(false)),
|
}));
|
||||||
};
|
|
||||||
|
|
||||||
let inode = state.fs.create_inode_with_default_stat(
|
let inode = state.fs.create_inode_with_default_stat(
|
||||||
inodes.deref_mut(),
|
inodes.deref(),
|
||||||
kind,
|
kind,
|
||||||
false,
|
false,
|
||||||
"event".to_string().into(),
|
"event".to_string().into(),
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ pub fn fd_fdstat_get<M: MemorySize>(
|
|||||||
);
|
);
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
||||||
let stat = wasi_try!(state.fs.fdstat(inodes.deref(), fd));
|
let stat = wasi_try!(state.fs.fdstat(fd));
|
||||||
|
|
||||||
let buf = buf_ptr.deref(&memory);
|
let buf = buf_ptr.deref(&memory);
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ pub fn fd_fdstat_set_flags(
|
|||||||
let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
||||||
let mut fd_map = state.fs.fd_map.write().unwrap();
|
let mut fd_map = state.fs.fd_map.write().unwrap();
|
||||||
let fd_entry = wasi_try_ok!(fd_map.get_mut(&fd).ok_or(Errno::Badf));
|
let fd_entry = wasi_try_ok!(fd_map.get_mut(&fd).ok_or(Errno::Badf));
|
||||||
let inode = fd_entry.inode;
|
let inode = fd_entry.inode.clone();
|
||||||
|
|
||||||
if !fd_entry.rights.contains(Rights::FD_FDSTAT_SET_FLAGS) {
|
if !fd_entry.rights.contains(Rights::FD_FDSTAT_SET_FLAGS) {
|
||||||
debug!(
|
debug!(
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ pub(crate) fn fd_filestat_get_internal<M: MemorySize>(
|
|||||||
return Errno::Access;
|
return Errno::Access;
|
||||||
}
|
}
|
||||||
|
|
||||||
let stat = wasi_try!(state.fs.filestat_fd(inodes.deref(), fd));
|
let stat = wasi_try!(state.fs.filestat_fd(fd));
|
||||||
|
|
||||||
let buf = buf.deref(&memory);
|
let buf = buf.deref(&memory);
|
||||||
wasi_try_mem!(buf.write(stat));
|
wasi_try_mem!(buf.write(stat));
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ pub fn fd_filestat_set_size(
|
|||||||
ctx.data().tid()
|
ctx.data().tid()
|
||||||
);
|
);
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
let (_, mut state) = env.get_memory_and_wasi_state(&ctx, 0);
|
||||||
let fd_entry = wasi_try!(state.fs.get_fd(fd));
|
let fd_entry = wasi_try!(state.fs.get_fd(fd));
|
||||||
let inode = fd_entry.inode;
|
let inode = fd_entry.inode;
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ pub fn fd_filestat_set_size(
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut guard = inodes.arena[inode].write();
|
let mut guard = inode.write();
|
||||||
match guard.deref_mut() {
|
match guard.deref_mut() {
|
||||||
Kind::File { handle, .. } => {
|
Kind::File { handle, .. } => {
|
||||||
if let Some(handle) = handle {
|
if let Some(handle) = handle {
|
||||||
@@ -48,7 +48,7 @@ pub fn fd_filestat_set_size(
|
|||||||
Kind::Dir { .. } | Kind::Root { .. } => return Errno::Isdir,
|
Kind::Dir { .. } | Kind::Root { .. } => return Errno::Isdir,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inodes.arena[inode].stat.write().unwrap().st_size = st_size;
|
inode.stat.write().unwrap().st_size = st_size;
|
||||||
|
|
||||||
Errno::Success
|
Errno::Success
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ pub fn fd_filestat_set_times(
|
|||||||
ctx.data().tid()
|
ctx.data().tid()
|
||||||
);
|
);
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
let (_, mut state) = env.get_memory_and_wasi_state(&ctx, 0);
|
||||||
let fd_entry = wasi_try!(state.fs.get_fd(fd));
|
let fd_entry = wasi_try!(state.fs.get_fd(fd));
|
||||||
|
|
||||||
if !fd_entry.rights.contains(Rights::FD_FILESTAT_SET_TIMES) {
|
if !fd_entry.rights.contains(Rights::FD_FILESTAT_SET_TIMES) {
|
||||||
@@ -36,8 +36,7 @@ pub fn fd_filestat_set_times(
|
|||||||
return Errno::Inval;
|
return Errno::Inval;
|
||||||
}
|
}
|
||||||
|
|
||||||
let inode_idx = fd_entry.inode;
|
let inode = fd_entry.inode;
|
||||||
let inode = &inodes.arena[inode_idx];
|
|
||||||
|
|
||||||
if fst_flags.contains(Fstflags::SET_ATIM) || fst_flags.contains(Fstflags::SET_ATIM_NOW) {
|
if fst_flags.contains(Fstflags::SET_ATIM) || fst_flags.contains(Fstflags::SET_ATIM_NOW) {
|
||||||
let time_to_set = if fst_flags.contains(Fstflags::SET_ATIM) {
|
let time_to_set = if fst_flags.contains(Fstflags::SET_ATIM) {
|
||||||
|
|||||||
@@ -15,25 +15,24 @@ pub fn fd_prestat_dir_name<M: MemorySize>(
|
|||||||
path_len
|
path_len
|
||||||
);
|
);
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
let (memory, mut state) = env.get_memory_and_wasi_state(&ctx, 0);
|
||||||
let path_chars = wasi_try_mem!(path.slice(&memory, path_len));
|
let path_chars = wasi_try_mem!(path.slice(&memory, path_len));
|
||||||
|
|
||||||
let real_inode = wasi_try!(state.fs.get_fd_inode(fd));
|
let inode = wasi_try!(state.fs.get_fd_inode(fd));
|
||||||
let inode_val = &inodes.arena[real_inode];
|
|
||||||
|
|
||||||
// check inode-val.is_preopened?
|
// check inode-val.is_preopened?
|
||||||
|
|
||||||
trace!("=> inode: {:?}", inode_val);
|
trace!("=> inode: {:?}", inode);
|
||||||
let guard = inode_val.read();
|
let guard = inode.read();
|
||||||
match guard.deref() {
|
match guard.deref() {
|
||||||
Kind::Dir { .. } | Kind::Root { .. } => {
|
Kind::Dir { .. } | Kind::Root { .. } => {
|
||||||
// TODO: verify this: null termination, etc
|
// TODO: verify this: null termination, etc
|
||||||
let path_len: u64 = path_len.into();
|
let path_len: u64 = path_len.into();
|
||||||
if (inode_val.name.len() as u64) < path_len {
|
if (inode.name.len() as u64) < path_len {
|
||||||
wasi_try_mem!(path_chars
|
wasi_try_mem!(path_chars
|
||||||
.subslice(0..inode_val.name.len() as u64)
|
.subslice(0..inode.name.len() as u64)
|
||||||
.write_slice(inode_val.name.as_bytes()));
|
.write_slice(inode.name.as_bytes()));
|
||||||
wasi_try_mem!(path_chars.index(inode_val.name.len() as u64).write(0));
|
wasi_try_mem!(path_chars.index(inode.name.len() as u64).write(0));
|
||||||
|
|
||||||
//trace!("=> result: \"{}\"", inode_val.name);
|
//trace!("=> result: \"{}\"", inode_val.name);
|
||||||
|
|
||||||
|
|||||||
@@ -21,16 +21,14 @@ pub fn fd_prestat_get<M: MemorySize>(
|
|||||||
fd
|
fd
|
||||||
);
|
);
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
let (memory, mut state) = env.get_memory_and_wasi_state(&ctx, 0);
|
||||||
|
|
||||||
let prestat_ptr = buf.deref(&memory);
|
let prestat_ptr = buf.deref(&memory);
|
||||||
wasi_try_mem!(
|
wasi_try_mem!(
|
||||||
prestat_ptr.write(wasi_try!(state.fs.prestat_fd(inodes.deref(), fd).map_err(
|
prestat_ptr.write(wasi_try!(state.fs.prestat_fd(fd).map_err(|code| {
|
||||||
|code| {
|
debug!("fd_prestat_get failed (fd={}) - errno={}", fd, code);
|
||||||
debug!("fd_prestat_get failed (fd={}) - errno={}", fd, code);
|
code
|
||||||
code
|
})))
|
||||||
}
|
|
||||||
)))
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Errno::Success
|
Errno::Success
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
use std::{collections::VecDeque, task::Waker};
|
||||||
|
|
||||||
use wasmer_vfs::AsyncReadExt;
|
use wasmer_vfs::AsyncReadExt;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::syscalls::*;
|
use crate::{fs::NotificationInner, syscalls::*};
|
||||||
|
|
||||||
/// ### `fd_read()`
|
/// ### `fd_read()`
|
||||||
/// Read data from file descriptor
|
/// Read data from file descriptor
|
||||||
@@ -35,15 +37,45 @@ pub fn fd_read<M: MemorySize>(
|
|||||||
fd_entry.offset.load(Ordering::Acquire) as usize
|
fd_entry.offset.load(Ordering::Acquire) as usize
|
||||||
};
|
};
|
||||||
|
|
||||||
let ret = fd_read_internal::<M>(ctx, fd, iovs, iovs_len, offset, nread, true);
|
let res = fd_read_internal::<M>(&mut ctx, fd, iovs, iovs_len, offset, nread, true)?;
|
||||||
trace!(
|
|
||||||
%fd,
|
let mut ret = Errno::Success;
|
||||||
"wasi[{}:{}]::fd_read - {:?}",
|
let bytes_read = match res {
|
||||||
pid,
|
Ok(bytes_read) => {
|
||||||
tid,
|
trace!(
|
||||||
ret
|
%fd,
|
||||||
);
|
%bytes_read,
|
||||||
ret
|
"wasi[{}:{}]::fd_read",
|
||||||
|
ctx.data().pid(),
|
||||||
|
ctx.data().tid(),
|
||||||
|
);
|
||||||
|
bytes_read
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
let read_err = err.name();
|
||||||
|
trace!(
|
||||||
|
%fd,
|
||||||
|
%read_err,
|
||||||
|
"wasi[{}:{}]::fd_read",
|
||||||
|
ctx.data().pid(),
|
||||||
|
ctx.data().tid(),
|
||||||
|
);
|
||||||
|
ret = err;
|
||||||
|
0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let bytes_read: M::Offset = wasi_try_ok!(bytes_read.try_into().map_err(|_| Errno::Overflow));
|
||||||
|
|
||||||
|
let env = ctx.data();
|
||||||
|
let memory = env.memory_view(&ctx);
|
||||||
|
|
||||||
|
let env = ctx.data();
|
||||||
|
let memory = env.memory_view(&ctx);
|
||||||
|
let nread_ref = nread.deref(&memory);
|
||||||
|
wasi_try_mem_ok!(nread_ref.write(bytes_read));
|
||||||
|
|
||||||
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ### `fd_pread()`
|
/// ### `fd_pread()`
|
||||||
@@ -62,7 +94,7 @@ pub fn fd_read<M: MemorySize>(
|
|||||||
/// - `size_t nread`
|
/// - `size_t nread`
|
||||||
/// The number of bytes read
|
/// The number of bytes read
|
||||||
pub fn fd_pread<M: MemorySize>(
|
pub fn fd_pread<M: MemorySize>(
|
||||||
ctx: FunctionEnvMut<'_, WasiEnv>,
|
mut ctx: FunctionEnvMut<'_, WasiEnv>,
|
||||||
fd: WasiFd,
|
fd: WasiFd,
|
||||||
iovs: WasmPtr<__wasi_iovec_t<M>, M>,
|
iovs: WasmPtr<__wasi_iovec_t<M>, M>,
|
||||||
iovs_len: M::Offset,
|
iovs_len: M::Offset,
|
||||||
@@ -72,86 +104,100 @@ pub fn fd_pread<M: MemorySize>(
|
|||||||
let pid = ctx.data().pid();
|
let pid = ctx.data().pid();
|
||||||
let tid = ctx.data().tid();
|
let tid = ctx.data().tid();
|
||||||
|
|
||||||
let ret = fd_read_internal::<M>(ctx, fd, iovs, iovs_len, offset as usize, nread, false);
|
let res = fd_read_internal::<M>(&mut ctx, fd, iovs, iovs_len, offset as usize, nread, false)?;
|
||||||
trace!(
|
|
||||||
%fd,
|
let mut ret = Errno::Success;
|
||||||
%offset,
|
let bytes_read = match res {
|
||||||
"wasi[{}:{}]::fd_pread - {:?}",
|
Ok(bytes_read) => {
|
||||||
pid,
|
trace!(
|
||||||
tid,
|
%fd,
|
||||||
ret
|
%offset,
|
||||||
);
|
%bytes_read,
|
||||||
ret
|
"wasi[{}:{}]::fd_pread - {:?}",
|
||||||
|
ctx.data().pid(),
|
||||||
|
ctx.data().tid(),
|
||||||
|
ret
|
||||||
|
);
|
||||||
|
bytes_read
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
let read_err = err.name();
|
||||||
|
trace!(
|
||||||
|
%fd,
|
||||||
|
%offset,
|
||||||
|
%read_err,
|
||||||
|
"wasi[{}:{}]::fd_pread - {:?}",
|
||||||
|
ctx.data().pid(),
|
||||||
|
ctx.data().tid(),
|
||||||
|
ret
|
||||||
|
);
|
||||||
|
ret = err;
|
||||||
|
0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let bytes_read: M::Offset = wasi_try_ok!(bytes_read.try_into().map_err(|_| Errno::Overflow));
|
||||||
|
|
||||||
|
let env = ctx.data();
|
||||||
|
let memory = env.memory_view(&ctx);
|
||||||
|
|
||||||
|
let env = ctx.data();
|
||||||
|
let memory = env.memory_view(&ctx);
|
||||||
|
let nread_ref = nread.deref(&memory);
|
||||||
|
wasi_try_mem_ok!(nread_ref.write(bytes_read));
|
||||||
|
|
||||||
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ### `fd_pread()`
|
|
||||||
/// Read from the file at the given offset without updating the file cursor.
|
|
||||||
/// This acts like a stateless version of Seek + Read
|
|
||||||
/// Inputs:
|
|
||||||
/// - `Fd fd`
|
|
||||||
/// The file descriptor to read the data with
|
|
||||||
/// - `const __wasi_iovec_t* iovs'
|
|
||||||
/// Vectors where the data will be stored
|
|
||||||
/// - `size_t iovs_len`
|
|
||||||
/// The number of vectors to store the data into
|
|
||||||
/// - `Filesize offset`
|
|
||||||
/// The file cursor to use: the starting position from which data will be read
|
|
||||||
/// Output:
|
|
||||||
/// - `size_t nread`
|
|
||||||
/// The number of bytes read
|
|
||||||
fn fd_read_internal<M: MemorySize>(
|
fn fd_read_internal<M: MemorySize>(
|
||||||
mut ctx: FunctionEnvMut<'_, WasiEnv>,
|
ctx: &mut FunctionEnvMut<'_, WasiEnv>,
|
||||||
fd: WasiFd,
|
fd: WasiFd,
|
||||||
iovs: WasmPtr<__wasi_iovec_t<M>, M>,
|
iovs: WasmPtr<__wasi_iovec_t<M>, M>,
|
||||||
iovs_len: M::Offset,
|
iovs_len: M::Offset,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
nread: WasmPtr<M::Offset, M>,
|
nread: WasmPtr<M::Offset, M>,
|
||||||
should_update_cursor: bool,
|
should_update_cursor: bool,
|
||||||
) -> Result<Errno, WasiError> {
|
) -> Result<Result<usize, Errno>, WasiError> {
|
||||||
wasi_try_ok!(WasiEnv::process_signals_and_exit(&mut ctx)?);
|
wasi_try_ok_ok!(WasiEnv::process_signals_and_exit(ctx)?);
|
||||||
|
|
||||||
let mut env = ctx.data();
|
let mut env = ctx.data();
|
||||||
let state = env.state.clone();
|
let state = env.state.clone();
|
||||||
let inodes = state.inodes.clone();
|
|
||||||
|
|
||||||
let fd_entry = wasi_try_ok!(state.fs.get_fd(fd));
|
let fd_entry = wasi_try_ok_ok!(state.fs.get_fd(fd));
|
||||||
let is_stdio = fd_entry.is_stdio;
|
let is_stdio = fd_entry.is_stdio;
|
||||||
|
|
||||||
let bytes_read = {
|
let bytes_read = {
|
||||||
if !is_stdio && !fd_entry.rights.contains(Rights::FD_READ) {
|
if !is_stdio && !fd_entry.rights.contains(Rights::FD_READ) {
|
||||||
// TODO: figure out the error to return when lacking rights
|
// TODO: figure out the error to return when lacking rights
|
||||||
return Ok(Errno::Access);
|
return Ok(Err(Errno::Access));
|
||||||
}
|
}
|
||||||
|
|
||||||
let inode_idx = fd_entry.inode;
|
let inode = fd_entry.inode;
|
||||||
let fd_flags = fd_entry.flags;
|
let fd_flags = fd_entry.flags;
|
||||||
|
|
||||||
let max_size = {
|
let max_size = {
|
||||||
let memory = env.memory_view(&ctx);
|
let memory = env.memory_view(ctx);
|
||||||
let iovs_arr = wasi_try_mem_ok!(iovs.slice(&memory, iovs_len));
|
let iovs_arr = wasi_try_mem_ok_ok!(iovs.slice(&memory, iovs_len));
|
||||||
let mut max_size = 0usize;
|
let mut max_size = 0usize;
|
||||||
for iovs in iovs_arr.iter() {
|
for iovs in iovs_arr.iter() {
|
||||||
let iovs = wasi_try_mem_ok!(iovs.read());
|
let iovs = wasi_try_mem_ok_ok!(iovs.read());
|
||||||
let buf_len: usize =
|
let buf_len: usize =
|
||||||
wasi_try_ok!(iovs.buf_len.try_into().map_err(|_| Errno::Overflow));
|
wasi_try_ok_ok!(iovs.buf_len.try_into().map_err(|_| Errno::Overflow));
|
||||||
max_size += buf_len;
|
max_size += buf_len;
|
||||||
}
|
}
|
||||||
max_size
|
max_size
|
||||||
};
|
};
|
||||||
|
|
||||||
let (bytes_read, can_update_cursor) = {
|
let (bytes_read, can_update_cursor) = {
|
||||||
let inodes = inodes.read().unwrap();
|
|
||||||
let inode = &inodes.arena[inode_idx];
|
|
||||||
let mut guard = inode.write();
|
let mut guard = inode.write();
|
||||||
match guard.deref_mut() {
|
match guard.deref_mut() {
|
||||||
Kind::File { handle, .. } => {
|
Kind::File { handle, .. } => {
|
||||||
if let Some(handle) = handle {
|
if let Some(handle) = handle {
|
||||||
let handle = handle.clone();
|
let handle = handle.clone();
|
||||||
drop(guard);
|
drop(guard);
|
||||||
drop(inodes);
|
|
||||||
|
|
||||||
let data = wasi_try_ok!(__asyncify(
|
let data = wasi_try_ok_ok!(__asyncify(
|
||||||
&mut ctx,
|
ctx,
|
||||||
if fd_flags.contains(Fdflags::NONBLOCK) {
|
if fd_flags.contains(Fdflags::NONBLOCK) {
|
||||||
Some(Duration::ZERO)
|
Some(Duration::ZERO)
|
||||||
} else {
|
} else {
|
||||||
@@ -166,8 +212,7 @@ fn fd_read_internal<M: MemorySize>(
|
|||||||
.map_err(map_io_err)?;
|
.map_err(map_io_err)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: optimize with MaybeUninit
|
let mut data = Vec::with_capacity(max_size);
|
||||||
let mut data = vec![0u8; max_size];
|
|
||||||
unsafe { data.set_len(max_size) };
|
unsafe { data.set_len(max_size) };
|
||||||
let amt = handle.read(&mut data[..]).await.map_err(|err| {
|
let amt = handle.read(&mut data[..]).await.map_err(|err| {
|
||||||
let err = From::<std::io::Error>::from(err);
|
let err = From::<std::io::Error>::from(err);
|
||||||
@@ -193,22 +238,21 @@ fn fd_read_internal<M: MemorySize>(
|
|||||||
env = ctx.data();
|
env = ctx.data();
|
||||||
|
|
||||||
let memory = env.memory_view(&ctx);
|
let memory = env.memory_view(&ctx);
|
||||||
let iovs_arr = wasi_try_mem_ok!(iovs.slice(&memory, iovs_len));
|
let iovs_arr = wasi_try_mem_ok_ok!(iovs.slice(&memory, iovs_len));
|
||||||
let read = wasi_try_ok!(read_bytes(&data[..], &memory, iovs_arr));
|
let read = wasi_try_ok_ok!(read_bytes(&data[..], &memory, iovs_arr));
|
||||||
(read, true)
|
(read, true)
|
||||||
} else {
|
} else {
|
||||||
return Ok(Errno::Inval);
|
return Ok(Err(Errno::Badf));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Kind::Socket { socket } => {
|
Kind::Socket { socket } => {
|
||||||
let socket = socket.clone();
|
let socket = socket.clone();
|
||||||
|
|
||||||
drop(guard);
|
drop(guard);
|
||||||
drop(inodes);
|
|
||||||
|
|
||||||
let tasks = env.tasks.clone();
|
let tasks = env.tasks.clone();
|
||||||
let res = __asyncify(
|
let res = __asyncify(
|
||||||
&mut ctx,
|
ctx,
|
||||||
if fd_flags.contains(Fdflags::NONBLOCK) {
|
if fd_flags.contains(Fdflags::NONBLOCK) {
|
||||||
Some(Duration::ZERO)
|
Some(Duration::ZERO)
|
||||||
} else {
|
} else {
|
||||||
@@ -238,14 +282,14 @@ fn fd_read_internal<M: MemorySize>(
|
|||||||
match res {
|
match res {
|
||||||
Err(Errno::Connaborted) | Err(Errno::Connreset) => (0, false),
|
Err(Errno::Connaborted) | Err(Errno::Connreset) => (0, false),
|
||||||
res => {
|
res => {
|
||||||
let data = wasi_try_ok!(res);
|
let data = wasi_try_ok_ok!(res);
|
||||||
env = ctx.data();
|
env = ctx.data();
|
||||||
|
|
||||||
let data_len = data.len();
|
let data_len = data.len();
|
||||||
let mut reader = &data[..];
|
let mut reader = &data[..];
|
||||||
let memory = env.memory_view(&ctx);
|
let memory = env.memory_view(&ctx);
|
||||||
let iovs_arr = wasi_try_mem_ok!(iovs.slice(&memory, iovs_len));
|
let iovs_arr = wasi_try_mem_ok_ok!(iovs.slice(&memory, iovs_len));
|
||||||
let bytes_read = wasi_try_ok!(
|
let bytes_read = wasi_try_ok_ok!(
|
||||||
read_bytes(reader, &memory, iovs_arr).map(|_| data_len)
|
read_bytes(reader, &memory, iovs_arr).map(|_| data_len)
|
||||||
);
|
);
|
||||||
(bytes_read, false)
|
(bytes_read, false)
|
||||||
@@ -256,10 +300,9 @@ fn fd_read_internal<M: MemorySize>(
|
|||||||
let mut pipe = pipe.clone();
|
let mut pipe = pipe.clone();
|
||||||
|
|
||||||
drop(guard);
|
drop(guard);
|
||||||
drop(inodes);
|
|
||||||
|
|
||||||
let data = wasi_try_ok!(__asyncify(
|
let data = wasi_try_ok_ok!(__asyncify(
|
||||||
&mut ctx,
|
ctx,
|
||||||
if fd_flags.contains(Fdflags::NONBLOCK) {
|
if fd_flags.contains(Fdflags::NONBLOCK) {
|
||||||
Some(Duration::ZERO)
|
Some(Duration::ZERO)
|
||||||
} else {
|
} else {
|
||||||
@@ -284,78 +327,103 @@ fn fd_read_internal<M: MemorySize>(
|
|||||||
let data_len = data.len();
|
let data_len = data.len();
|
||||||
let mut reader = &data[..];
|
let mut reader = &data[..];
|
||||||
|
|
||||||
let memory = env.memory_view(&ctx);
|
let memory = env.memory_view(ctx);
|
||||||
let iovs_arr = wasi_try_mem_ok!(iovs.slice(&memory, iovs_len));
|
let iovs_arr = wasi_try_mem_ok_ok!(iovs.slice(&memory, iovs_len));
|
||||||
let bytes_read =
|
let bytes_read =
|
||||||
wasi_try_ok!(read_bytes(reader, &memory, iovs_arr).map(|_| data_len));
|
wasi_try_ok_ok!(read_bytes(reader, &memory, iovs_arr).map(|_| data_len));
|
||||||
(bytes_read, false)
|
(bytes_read, false)
|
||||||
}
|
}
|
||||||
Kind::Dir { .. } | Kind::Root { .. } => {
|
Kind::Dir { .. } | Kind::Root { .. } => {
|
||||||
// TODO: verify
|
// TODO: verify
|
||||||
return Ok(Errno::Isdir);
|
return Ok(Err(Errno::Isdir));
|
||||||
}
|
}
|
||||||
Kind::EventNotifications {
|
Kind::EventNotifications(inner) => {
|
||||||
counter: ref_counter,
|
// Create a poller
|
||||||
is_semaphore: ref_is_semaphore,
|
struct NotifyPoller {
|
||||||
wakers: ref_wakers,
|
inner: Arc<NotificationInner>,
|
||||||
..
|
non_blocking: bool,
|
||||||
} => {
|
|
||||||
let counter = Arc::clone(ref_counter);
|
|
||||||
let is_semaphore: bool = *ref_is_semaphore;
|
|
||||||
let wakers = Arc::clone(ref_wakers);
|
|
||||||
|
|
||||||
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel();
|
|
||||||
{
|
|
||||||
let mut guard = wakers.lock().unwrap();
|
|
||||||
guard.push_front(tx);
|
|
||||||
}
|
}
|
||||||
|
let poller = NotifyPoller {
|
||||||
|
inner: inner.clone(),
|
||||||
|
non_blocking: fd_flags.contains(Fdflags::NONBLOCK),
|
||||||
|
};
|
||||||
|
|
||||||
drop(guard);
|
drop(guard);
|
||||||
drop(inodes);
|
|
||||||
|
|
||||||
let ret;
|
// The poller will register itself for notifications and wait for the
|
||||||
loop {
|
// counter to drop
|
||||||
let val = counter.load(Ordering::Acquire);
|
impl Future for NotifyPoller {
|
||||||
if val > 0 {
|
type Output = Result<u64, Errno>;
|
||||||
let new_val = if is_semaphore { val - 1 } else { 0 };
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
if counter
|
if !self.non_blocking {
|
||||||
.compare_exchange(val, new_val, Ordering::AcqRel, Ordering::Acquire)
|
let waker = cx.waker();
|
||||||
.is_ok()
|
let mut guard = self.inner.wakers.lock().unwrap();
|
||||||
{
|
if guard.iter().any(|w| w.will_wake(waker)) == false {
|
||||||
let mut memory = env.memory_view(&ctx);
|
guard.push_front(waker.clone());
|
||||||
let reader = val.to_ne_bytes();
|
}
|
||||||
let iovs_arr = wasi_try_mem_ok!(iovs.slice(&memory, iovs_len));
|
}
|
||||||
ret = wasi_try_ok!(read_bytes(&reader[..], &memory, iovs_arr));
|
|
||||||
break;
|
let wake_all = || {
|
||||||
} else {
|
self.inner.last_poll.store(u64::MAX, Ordering::Release);
|
||||||
continue;
|
let mut guard = self.inner.wakers.lock().unwrap();
|
||||||
|
while let Some(waker) = guard.pop_front() {
|
||||||
|
waker.wake();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let val = self.inner.counter.load(Ordering::Acquire);
|
||||||
|
if val > 0 {
|
||||||
|
let new_val = if self.inner.is_semaphore { val - 1 } else { 0 };
|
||||||
|
if self
|
||||||
|
.inner
|
||||||
|
.counter
|
||||||
|
.compare_exchange(
|
||||||
|
val,
|
||||||
|
new_val,
|
||||||
|
Ordering::AcqRel,
|
||||||
|
Ordering::Acquire,
|
||||||
|
)
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
wake_all();
|
||||||
|
return Poll::Ready(Ok(val));
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If its none blocking then exit
|
||||||
|
if self.non_blocking {
|
||||||
|
wake_all();
|
||||||
|
return Poll::Ready(Err(Errno::Again));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Poll::Pending;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If its none blocking then exit
|
// Yield until the notifications are triggered
|
||||||
if fd_flags.contains(Fdflags::NONBLOCK) {
|
let tasks_inner = env.tasks.clone();
|
||||||
return Ok(Errno::Again);
|
let val = wasi_try_ok_ok!(__asyncify(ctx, None, async { poller.await })?
|
||||||
}
|
|
||||||
|
|
||||||
// Yield until the notifications are triggered
|
|
||||||
let tasks_inner = env.tasks.clone();
|
|
||||||
rx = wasi_try_ok!(__asyncify(&mut ctx, None, async move {
|
|
||||||
let _ = rx.recv().await;
|
|
||||||
Ok(rx)
|
|
||||||
})?
|
|
||||||
.map_err(|err| match err {
|
.map_err(|err| match err {
|
||||||
Errno::Timedout => Errno::Again,
|
Errno::Timedout => Errno::Again,
|
||||||
a => a,
|
a => a,
|
||||||
}));
|
}));
|
||||||
env = ctx.data();
|
env = ctx.data();
|
||||||
}
|
|
||||||
|
let mut memory = env.memory_view(ctx);
|
||||||
|
let reader = val.to_ne_bytes();
|
||||||
|
let iovs_arr = wasi_try_mem_ok_ok!(iovs.slice(&memory, iovs_len));
|
||||||
|
let ret = wasi_try_ok_ok!(read_bytes(&reader[..], &memory, iovs_arr));
|
||||||
(ret, false)
|
(ret, false)
|
||||||
}
|
}
|
||||||
Kind::Symlink { .. } => unimplemented!("Symlinks in wasi::fd_read"),
|
Kind::Symlink { .. } => unimplemented!("Symlinks in wasi::fd_read"),
|
||||||
Kind::Buffer { buffer } => {
|
Kind::Buffer { buffer } => {
|
||||||
let memory = env.memory_view(&ctx);
|
let memory = env.memory_view(ctx);
|
||||||
let iovs_arr = wasi_try_mem_ok!(iovs.slice(&memory, iovs_len));
|
let iovs_arr = wasi_try_mem_ok_ok!(iovs.slice(&memory, iovs_len));
|
||||||
let read = wasi_try_ok!(read_bytes(&buffer[offset..], &memory, iovs_arr));
|
let read = wasi_try_ok_ok!(read_bytes(&buffer[offset..], &memory, iovs_arr));
|
||||||
(read, true)
|
(read, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -364,7 +432,7 @@ fn fd_read_internal<M: MemorySize>(
|
|||||||
if !is_stdio && should_update_cursor && can_update_cursor {
|
if !is_stdio && should_update_cursor && can_update_cursor {
|
||||||
// reborrow
|
// reborrow
|
||||||
let mut fd_map = state.fs.fd_map.write().unwrap();
|
let mut fd_map = state.fs.fd_map.write().unwrap();
|
||||||
let fd_entry = wasi_try_ok!(fd_map.get_mut(&fd).ok_or(Errno::Badf));
|
let fd_entry = wasi_try_ok_ok!(fd_map.get_mut(&fd).ok_or(Errno::Badf));
|
||||||
let old = fd_entry
|
let old = fd_entry
|
||||||
.offset
|
.offset
|
||||||
.fetch_add(bytes_read as u64, Ordering::AcqRel);
|
.fetch_add(bytes_read as u64, Ordering::AcqRel);
|
||||||
@@ -373,19 +441,5 @@ fn fd_read_internal<M: MemorySize>(
|
|||||||
bytes_read
|
bytes_read
|
||||||
};
|
};
|
||||||
|
|
||||||
let bytes_read: M::Offset = wasi_try_ok!(bytes_read.try_into().map_err(|_| Errno::Overflow));
|
Ok(Ok(bytes_read))
|
||||||
trace!(
|
|
||||||
"wasi[{}:{}]::fd_read: fd={},bytes_read={}",
|
|
||||||
ctx.data().pid(),
|
|
||||||
ctx.data().tid(),
|
|
||||||
fd,
|
|
||||||
bytes_read
|
|
||||||
);
|
|
||||||
|
|
||||||
let env = ctx.data();
|
|
||||||
let memory = env.memory_view(&ctx);
|
|
||||||
let nread_ref = nread.deref(&memory);
|
|
||||||
wasi_try_mem_ok!(nread_ref.write(bytes_read));
|
|
||||||
|
|
||||||
Ok(Errno::Success)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ pub fn fd_readdir<M: MemorySize>(
|
|||||||
ctx.data().tid()
|
ctx.data().tid()
|
||||||
);
|
);
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
let (memory, mut state) = env.get_memory_and_wasi_state(&ctx, 0);
|
||||||
// TODO: figure out how this is supposed to work;
|
// TODO: figure out how this is supposed to work;
|
||||||
// is it supposed to pack the buffer full every time until it can't? or do one at a time?
|
// is it supposed to pack the buffer full every time until it can't? or do one at a time?
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ pub fn fd_readdir<M: MemorySize>(
|
|||||||
let mut buf_idx = 0usize;
|
let mut buf_idx = 0usize;
|
||||||
|
|
||||||
let entries: Vec<(String, Filetype, u64)> = {
|
let entries: Vec<(String, Filetype, u64)> = {
|
||||||
let guard = inodes.arena[working_dir.inode].read();
|
let guard = working_dir.inode.read();
|
||||||
match guard.deref() {
|
match guard.deref() {
|
||||||
Kind::Dir { path, entries, .. } => {
|
Kind::Dir { path, entries, .. } => {
|
||||||
debug!("Reading dir {:?}", path);
|
debug!("Reading dir {:?}", path);
|
||||||
@@ -65,16 +65,12 @@ pub fn fd_readdir<M: MemorySize>(
|
|||||||
))
|
))
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<(String, Filetype, u64)>, _>>());
|
.collect::<Result<Vec<(String, Filetype, u64)>, _>>());
|
||||||
entry_vec.extend(
|
entry_vec.extend(entries.iter().filter(|(_, inode)| inode.is_preopened).map(
|
||||||
entries
|
|(name, inode)| {
|
||||||
.iter()
|
let stat = inode.stat.read().unwrap();
|
||||||
.filter(|(_, inode)| inodes.arena[**inode].is_preopened)
|
(inode.name.to_string(), stat.st_filetype, stat.st_ino)
|
||||||
.map(|(name, inode)| {
|
},
|
||||||
let entry = &inodes.arena[*inode];
|
));
|
||||||
let stat = entry.stat.read().unwrap();
|
|
||||||
(entry.name.to_string(), stat.st_filetype, stat.st_ino)
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
// adding . and .. special folders
|
// adding . and .. special folders
|
||||||
// TODO: inode
|
// TODO: inode
|
||||||
entry_vec.push((".".to_string(), Filetype::Directory, 0));
|
entry_vec.push((".".to_string(), Filetype::Directory, 0));
|
||||||
@@ -85,17 +81,18 @@ pub fn fd_readdir<M: MemorySize>(
|
|||||||
Kind::Root { entries } => {
|
Kind::Root { entries } => {
|
||||||
debug!("Reading root");
|
debug!("Reading root");
|
||||||
let sorted_entries = {
|
let sorted_entries = {
|
||||||
let mut entry_vec: Vec<(String, Inode)> =
|
let mut entry_vec: Vec<(String, InodeGuard)> = entries
|
||||||
entries.iter().map(|(a, b)| (a.clone(), *b)).collect();
|
.iter()
|
||||||
|
.map(|(a, b)| (a.clone(), b.clone()))
|
||||||
|
.collect();
|
||||||
entry_vec.sort_by(|a, b| a.0.cmp(&b.0));
|
entry_vec.sort_by(|a, b| a.0.cmp(&b.0));
|
||||||
entry_vec
|
entry_vec
|
||||||
};
|
};
|
||||||
sorted_entries
|
sorted_entries
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(name, inode)| {
|
.map(|(name, inode)| {
|
||||||
let entry = &inodes.arena[inode];
|
let stat = inode.stat.read().unwrap();
|
||||||
let stat = entry.stat.read().unwrap();
|
(format!("/{}", inode.name), stat.st_filetype, stat.st_ino)
|
||||||
(format!("/{}", entry.name), stat.st_filetype, stat.st_ino)
|
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,25 +20,18 @@ pub fn fd_renumber(ctx: FunctionEnvMut<'_, WasiEnv>, from: WasiFd, to: WasiFd) -
|
|||||||
return Errno::Success;
|
return Errno::Success;
|
||||||
}
|
}
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
let (_, mut state) = env.get_memory_and_wasi_state(&ctx, 0);
|
||||||
|
|
||||||
let mut fd_map = state.fs.fd_map.write().unwrap();
|
let mut fd_map = state.fs.fd_map.write().unwrap();
|
||||||
let fd_entry = wasi_try!(fd_map.get_mut(&from).ok_or(Errno::Badf));
|
let fd_entry = wasi_try!(fd_map.get_mut(&from).ok_or(Errno::Badf));
|
||||||
|
|
||||||
fd_entry.ref_cnt.fetch_add(1, Ordering::Acquire);
|
|
||||||
let new_fd_entry = Fd {
|
let new_fd_entry = Fd {
|
||||||
// TODO: verify this is correct
|
// TODO: verify this is correct
|
||||||
ref_cnt: fd_entry.ref_cnt.clone(),
|
|
||||||
offset: fd_entry.offset.clone(),
|
offset: fd_entry.offset.clone(),
|
||||||
rights: fd_entry.rights_inheriting,
|
rights: fd_entry.rights_inheriting,
|
||||||
|
inode: fd_entry.inode.clone(),
|
||||||
..*fd_entry
|
..*fd_entry
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(fd_entry) = fd_map.get(&to).cloned() {
|
|
||||||
if fd_entry.ref_cnt.fetch_sub(1, Ordering::AcqRel) == 1 {
|
|
||||||
wasi_try!(state.fs.close_fd_ext(inodes.deref(), &mut fd_map, to));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fd_map.insert(to, new_fd_entry);
|
fd_map.insert(to, new_fd_entry);
|
||||||
|
|
||||||
Errno::Success
|
Errno::Success
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ pub fn fd_seek<M: MemorySize>(
|
|||||||
|
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let state = env.state.clone();
|
let state = env.state.clone();
|
||||||
let (memory, _, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
let (memory, _) = env.get_memory_and_wasi_state(&ctx, 0);
|
||||||
let fd_entry = wasi_try_ok!(state.fs.get_fd(fd));
|
let fd_entry = wasi_try_ok!(state.fs.get_fd(fd));
|
||||||
|
|
||||||
if !fd_entry.rights.contains(Rights::FD_SEEK) {
|
if !fd_entry.rights.contains(Rights::FD_SEEK) {
|
||||||
@@ -60,15 +60,13 @@ pub fn fd_seek<M: MemorySize>(
|
|||||||
}
|
}
|
||||||
Whence::End => {
|
Whence::End => {
|
||||||
use std::io::SeekFrom;
|
use std::io::SeekFrom;
|
||||||
let inode_idx = fd_entry.inode;
|
let mut guard = fd_entry.inode.write();
|
||||||
let mut guard = inodes.arena[inode_idx].write();
|
|
||||||
let deref_mut = guard.deref_mut();
|
let deref_mut = guard.deref_mut();
|
||||||
match deref_mut {
|
match deref_mut {
|
||||||
Kind::File { ref mut handle, .. } => {
|
Kind::File { ref mut handle, .. } => {
|
||||||
if let Some(handle) = handle {
|
if let Some(handle) = handle {
|
||||||
let handle = handle.clone();
|
let handle = handle.clone();
|
||||||
drop(guard);
|
drop(guard);
|
||||||
drop(inodes);
|
|
||||||
|
|
||||||
wasi_try_ok!(__asyncify(&mut ctx, None, async move {
|
wasi_try_ok!(__asyncify(&mut ctx, None, async move {
|
||||||
let mut handle = handle.write().unwrap();
|
let mut handle = handle.write().unwrap();
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ pub fn fd_sync(mut ctx: FunctionEnvMut<'_, WasiEnv>, fd: WasiFd) -> Result<Errno
|
|||||||
debug!("wasi[{}:{}]::fd_sync", ctx.data().pid(), ctx.data().tid());
|
debug!("wasi[{}:{}]::fd_sync", ctx.data().pid(), ctx.data().tid());
|
||||||
debug!("=> fd={}", fd);
|
debug!("=> fd={}", fd);
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (_, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
let (_, mut state) = env.get_memory_and_wasi_state(&ctx, 0);
|
||||||
let fd_entry = wasi_try_ok!(state.fs.get_fd(fd));
|
let fd_entry = wasi_try_ok!(state.fs.get_fd(fd));
|
||||||
if !fd_entry.rights.contains(Rights::FD_SYNC) {
|
if !fd_entry.rights.contains(Rights::FD_SYNC) {
|
||||||
return Ok(Errno::Access);
|
return Ok(Errno::Access);
|
||||||
@@ -23,14 +23,12 @@ pub fn fd_sync(mut ctx: FunctionEnvMut<'_, WasiEnv>, fd: WasiFd) -> Result<Errno
|
|||||||
|
|
||||||
// TODO: implement this for more than files
|
// TODO: implement this for more than files
|
||||||
{
|
{
|
||||||
let mut guard = inodes.arena[inode].write();
|
let mut guard = inode.write();
|
||||||
match guard.deref_mut() {
|
match guard.deref_mut() {
|
||||||
Kind::File { handle, .. } => {
|
Kind::File { handle, .. } => {
|
||||||
if let Some(handle) = handle {
|
if let Some(handle) = handle {
|
||||||
let handle = handle.clone();
|
let handle = handle.clone();
|
||||||
drop(fd_entry);
|
|
||||||
drop(guard);
|
drop(guard);
|
||||||
drop(inodes);
|
|
||||||
|
|
||||||
let size = {
|
let size = {
|
||||||
wasi_try_ok!(__asyncify(&mut ctx, None, async move {
|
wasi_try_ok!(__asyncify(&mut ctx, None, async move {
|
||||||
@@ -45,11 +43,11 @@ pub fn fd_sync(mut ctx: FunctionEnvMut<'_, WasiEnv>, fd: WasiFd) -> Result<Errno
|
|||||||
{
|
{
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (_, mut state, inodes) =
|
let (_, mut state, inodes) =
|
||||||
env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0);
|
env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
||||||
|
|
||||||
let fd_entry = wasi_try_ok!(state.fs.get_fd(fd));
|
let fd_entry = wasi_try_ok!(state.fs.get_fd(fd));
|
||||||
let inode = fd_entry.inode;
|
let inode = fd_entry.inode;
|
||||||
let mut guard = inodes.arena[inode].stat.write().unwrap();
|
let mut guard = inode.stat.write().unwrap();
|
||||||
guard.st_size = size;
|
guard.st_size = size;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -113,18 +113,15 @@ fn fd_write_internal<M: MemorySize>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let fd_flags = fd_entry.flags;
|
let fd_flags = fd_entry.flags;
|
||||||
let inode_idx = fd_entry.inode;
|
|
||||||
|
|
||||||
let (bytes_written, can_update_cursor) = {
|
let (bytes_written, can_update_cursor) = {
|
||||||
let (mut memory, _, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
let (mut memory, _) = env.get_memory_and_wasi_state(&ctx, 0);
|
||||||
let inode = &inodes.arena[inode_idx];
|
let mut guard = fd_entry.inode.write();
|
||||||
let mut guard = inode.write();
|
|
||||||
match guard.deref_mut() {
|
match guard.deref_mut() {
|
||||||
Kind::File { handle, .. } => {
|
Kind::File { handle, .. } => {
|
||||||
if let Some(handle) = handle {
|
if let Some(handle) = handle {
|
||||||
let handle = handle.clone();
|
let handle = handle.clone();
|
||||||
drop(guard);
|
drop(guard);
|
||||||
drop(inodes);
|
|
||||||
|
|
||||||
let buf_len: M::Offset = iovs_arr
|
let buf_len: M::Offset = iovs_arr
|
||||||
.iter()
|
.iter()
|
||||||
@@ -168,7 +165,6 @@ fn fd_write_internal<M: MemorySize>(
|
|||||||
Kind::Socket { socket } => {
|
Kind::Socket { socket } => {
|
||||||
let socket = socket.clone();
|
let socket = socket.clone();
|
||||||
drop(guard);
|
drop(guard);
|
||||||
drop(inodes);
|
|
||||||
|
|
||||||
let buf_len: M::Offset = iovs_arr
|
let buf_len: M::Offset = iovs_arr
|
||||||
.iter()
|
.iter()
|
||||||
@@ -203,12 +199,7 @@ fn fd_write_internal<M: MemorySize>(
|
|||||||
// TODO: verify
|
// TODO: verify
|
||||||
return Ok(Errno::Isdir);
|
return Ok(Errno::Isdir);
|
||||||
}
|
}
|
||||||
Kind::EventNotifications {
|
Kind::EventNotifications(inner) => {
|
||||||
counter,
|
|
||||||
wakers,
|
|
||||||
immediate,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let mut val: [MaybeUninit<u8>; 8] =
|
let mut val: [MaybeUninit<u8>; 8] =
|
||||||
unsafe { MaybeUninit::uninit().assume_init() };
|
unsafe { MaybeUninit::uninit().assume_init() };
|
||||||
let written = wasi_try_ok!(copy_to_slice(&memory, iovs_arr, &mut val[..]));
|
let written = wasi_try_ok!(copy_to_slice(&memory, iovs_arr, &mut val[..]));
|
||||||
@@ -217,12 +208,12 @@ fn fd_write_internal<M: MemorySize>(
|
|||||||
}
|
}
|
||||||
let val = u64::from_ne_bytes(unsafe { std::mem::transmute(val) });
|
let val = u64::from_ne_bytes(unsafe { std::mem::transmute(val) });
|
||||||
|
|
||||||
counter.fetch_add(val, Ordering::AcqRel);
|
inner.counter.fetch_add(val, Ordering::AcqRel);
|
||||||
|
inner.last_poll.store(u64::MAX, Ordering::Release);
|
||||||
{
|
{
|
||||||
let mut guard = wakers.lock().unwrap();
|
let mut guard = inner.wakers.lock().unwrap();
|
||||||
immediate.store(true, Ordering::Release);
|
|
||||||
while let Some(wake) = guard.pop_back() {
|
while let Some(wake) = guard.pop_back() {
|
||||||
let _ = wake.send(());
|
wake.wake();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,9 +243,8 @@ fn fd_write_internal<M: MemorySize>(
|
|||||||
// we set the size but we don't return any errors if it fails as
|
// we set the size but we don't return any errors if it fails as
|
||||||
// pipes and sockets will not do anything with this
|
// pipes and sockets will not do anything with this
|
||||||
let (mut memory, _, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
let (mut memory, _, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
||||||
let inode = &inodes.arena[inode_idx];
|
|
||||||
// Cast is valid because we don't support 128 bit systems...
|
// Cast is valid because we don't support 128 bit systems...
|
||||||
inode.stat.write().unwrap().st_size += bytes_written as u64;
|
fd_entry.inode.stat.write().unwrap().st_size += bytes_written as u64;
|
||||||
}
|
}
|
||||||
bytes_written
|
bytes_written
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,11 +26,11 @@ pub fn path_create_directory<M: MemorySize>(
|
|||||||
ctx.data().tid()
|
ctx.data().tid()
|
||||||
);
|
);
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0);
|
let (memory, state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
||||||
|
|
||||||
let working_dir = wasi_try!(state.fs.get_fd(fd));
|
let working_dir = wasi_try!(state.fs.get_fd(fd));
|
||||||
{
|
{
|
||||||
let guard = inodes.arena[working_dir.inode].read();
|
let guard = working_dir.inode.read();
|
||||||
if let Kind::Root { .. } = guard.deref() {
|
if let Kind::Root { .. } = guard.deref() {
|
||||||
return Errno::Access;
|
return Errno::Access;
|
||||||
}
|
}
|
||||||
@@ -71,7 +71,9 @@ pub fn path_create_directory<M: MemorySize>(
|
|||||||
let mut cur_dir_inode = working_dir.inode;
|
let mut cur_dir_inode = working_dir.inode;
|
||||||
for comp in &path_vec {
|
for comp in &path_vec {
|
||||||
debug!("Creating dir {}", comp);
|
debug!("Creating dir {}", comp);
|
||||||
let mut guard = inodes.arena[cur_dir_inode].write();
|
|
||||||
|
let processing_cur_dir_inode = cur_dir_inode.clone();
|
||||||
|
let mut guard = processing_cur_dir_inode.write();
|
||||||
match guard.deref_mut() {
|
match guard.deref_mut() {
|
||||||
Kind::Dir {
|
Kind::Dir {
|
||||||
ref mut entries,
|
ref mut entries,
|
||||||
@@ -80,8 +82,8 @@ pub fn path_create_directory<M: MemorySize>(
|
|||||||
} => {
|
} => {
|
||||||
match comp.borrow() {
|
match comp.borrow() {
|
||||||
".." => {
|
".." => {
|
||||||
if let Some(p) = parent {
|
if let Some(p) = parent.upgrade() {
|
||||||
cur_dir_inode = *p;
|
cur_dir_inode = p;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,7 +91,7 @@ pub fn path_create_directory<M: MemorySize>(
|
|||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
if let Some(child) = entries.get(comp) {
|
if let Some(child) = entries.get(comp) {
|
||||||
cur_dir_inode = *child;
|
cur_dir_inode = child.clone();
|
||||||
} else {
|
} else {
|
||||||
let mut adjusted_path = path.clone();
|
let mut adjusted_path = path.clone();
|
||||||
drop(guard);
|
drop(guard);
|
||||||
@@ -99,7 +101,7 @@ pub fn path_create_directory<M: MemorySize>(
|
|||||||
if let Ok(adjusted_path_stat) = path_filestat_get_internal(
|
if let Ok(adjusted_path_stat) = path_filestat_get_internal(
|
||||||
&memory,
|
&memory,
|
||||||
state,
|
state,
|
||||||
inodes.deref_mut(),
|
inodes,
|
||||||
fd,
|
fd,
|
||||||
0,
|
0,
|
||||||
&adjusted_path.to_string_lossy(),
|
&adjusted_path.to_string_lossy(),
|
||||||
@@ -111,25 +113,21 @@ pub fn path_create_directory<M: MemorySize>(
|
|||||||
wasi_try!(state.fs_create_dir(&adjusted_path));
|
wasi_try!(state.fs_create_dir(&adjusted_path));
|
||||||
}
|
}
|
||||||
let kind = Kind::Dir {
|
let kind = Kind::Dir {
|
||||||
parent: Some(cur_dir_inode),
|
parent: cur_dir_inode.downgrade(),
|
||||||
path: adjusted_path,
|
path: adjusted_path,
|
||||||
entries: Default::default(),
|
entries: Default::default(),
|
||||||
};
|
};
|
||||||
let new_inode = wasi_try!(state.fs.create_inode(
|
let new_inode =
|
||||||
inodes.deref_mut(),
|
wasi_try!(state.fs.create_inode(inodes, kind, false, comp.to_string()));
|
||||||
kind,
|
|
||||||
false,
|
|
||||||
comp.to_string()
|
|
||||||
));
|
|
||||||
|
|
||||||
// reborrow to insert
|
// reborrow to insert
|
||||||
{
|
{
|
||||||
let mut guard = inodes.arena[cur_dir_inode].write();
|
let mut guard = cur_dir_inode.write();
|
||||||
if let Kind::Dir {
|
if let Kind::Dir {
|
||||||
ref mut entries, ..
|
ref mut entries, ..
|
||||||
} = guard.deref_mut()
|
} = guard.deref_mut()
|
||||||
{
|
{
|
||||||
entries.insert(comp.to_string(), new_inode);
|
entries.insert(comp.to_string(), new_inode.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cur_dir_inode = new_inode;
|
cur_dir_inode = new_inode;
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ pub fn path_filestat_get<M: MemorySize>(
|
|||||||
buf: WasmPtr<Filestat, M>,
|
buf: WasmPtr<Filestat, M>,
|
||||||
) -> Errno {
|
) -> Errno {
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0);
|
let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
||||||
|
|
||||||
let mut path_string = unsafe { get_input_str!(&memory, path, path_len) };
|
let mut path_string = unsafe { get_input_str!(&memory, path, path_len) };
|
||||||
debug!(
|
debug!(
|
||||||
@@ -49,7 +49,7 @@ pub fn path_filestat_get<M: MemorySize>(
|
|||||||
let stat = wasi_try!(path_filestat_get_internal(
|
let stat = wasi_try!(path_filestat_get_internal(
|
||||||
&memory,
|
&memory,
|
||||||
state,
|
state,
|
||||||
inodes.deref_mut(),
|
inodes,
|
||||||
fd,
|
fd,
|
||||||
flags,
|
flags,
|
||||||
&path_string
|
&path_string
|
||||||
@@ -77,7 +77,7 @@ pub fn path_filestat_get<M: MemorySize>(
|
|||||||
pub fn path_filestat_get_internal(
|
pub fn path_filestat_get_internal(
|
||||||
memory: &MemoryView,
|
memory: &MemoryView,
|
||||||
state: &WasiState,
|
state: &WasiState,
|
||||||
inodes: &mut crate::WasiInodes,
|
inodes: &crate::WasiInodes,
|
||||||
fd: WasiFd,
|
fd: WasiFd,
|
||||||
flags: LookupFlags,
|
flags: LookupFlags,
|
||||||
path_string: &str,
|
path_string: &str,
|
||||||
@@ -95,10 +95,10 @@ pub fn path_filestat_get_internal(
|
|||||||
path_string,
|
path_string,
|
||||||
flags & __WASI_LOOKUP_SYMLINK_FOLLOW != 0,
|
flags & __WASI_LOOKUP_SYMLINK_FOLLOW != 0,
|
||||||
)?;
|
)?;
|
||||||
if inodes.arena[file_inode].is_preopened {
|
if file_inode.is_preopened {
|
||||||
Ok(*inodes.arena[file_inode].stat.read().unwrap().deref())
|
Ok(file_inode.stat.read().unwrap().deref().clone())
|
||||||
} else {
|
} else {
|
||||||
let guard = inodes.arena[file_inode].read();
|
let guard = file_inode.read();
|
||||||
state.fs.get_stat_for_kind(inodes.deref(), guard.deref())
|
state.fs.get_stat_for_kind(guard.deref())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ pub fn path_filestat_set_times<M: MemorySize>(
|
|||||||
ctx.data().tid()
|
ctx.data().tid()
|
||||||
);
|
);
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0);
|
let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
||||||
let fd_entry = wasi_try!(state.fs.get_fd(fd));
|
let fd_entry = wasi_try!(state.fs.get_fd(fd));
|
||||||
let fd_inode = fd_entry.inode;
|
let fd_inode = fd_entry.inode;
|
||||||
if !fd_entry.rights.contains(Rights::PATH_FILESTAT_SET_TIMES) {
|
if !fd_entry.rights.contains(Rights::PATH_FILESTAT_SET_TIMES) {
|
||||||
@@ -61,25 +61,23 @@ pub fn path_filestat_set_times<M: MemorySize>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let file_inode = wasi_try!(state.fs.get_inode_at_path(
|
let file_inode = wasi_try!(state.fs.get_inode_at_path(
|
||||||
inodes.deref_mut(),
|
inodes,
|
||||||
fd,
|
fd,
|
||||||
&path_string,
|
&path_string,
|
||||||
flags & __WASI_LOOKUP_SYMLINK_FOLLOW != 0,
|
flags & __WASI_LOOKUP_SYMLINK_FOLLOW != 0,
|
||||||
));
|
));
|
||||||
let stat = {
|
let stat = {
|
||||||
let guard = inodes.arena[file_inode].read();
|
let guard = file_inode.read();
|
||||||
wasi_try!(state.fs.get_stat_for_kind(inodes.deref(), guard.deref()))
|
wasi_try!(state.fs.get_stat_for_kind(guard.deref()))
|
||||||
};
|
};
|
||||||
|
|
||||||
let inode = &inodes.arena[fd_inode];
|
|
||||||
|
|
||||||
if fst_flags.contains(Fstflags::SET_ATIM) || fst_flags.contains(Fstflags::SET_ATIM_NOW) {
|
if fst_flags.contains(Fstflags::SET_ATIM) || fst_flags.contains(Fstflags::SET_ATIM_NOW) {
|
||||||
let time_to_set = if fst_flags.contains(Fstflags::SET_ATIM) {
|
let time_to_set = if fst_flags.contains(Fstflags::SET_ATIM) {
|
||||||
st_atim
|
st_atim
|
||||||
} else {
|
} else {
|
||||||
wasi_try!(get_current_time_in_nanos())
|
wasi_try!(get_current_time_in_nanos())
|
||||||
};
|
};
|
||||||
inode.stat.write().unwrap().st_atim = time_to_set;
|
fd_inode.stat.write().unwrap().st_atim = time_to_set;
|
||||||
}
|
}
|
||||||
if fst_flags.contains(Fstflags::SET_MTIM) || fst_flags.contains(Fstflags::SET_MTIM_NOW) {
|
if fst_flags.contains(Fstflags::SET_MTIM) || fst_flags.contains(Fstflags::SET_MTIM_NOW) {
|
||||||
let time_to_set = if fst_flags.contains(Fstflags::SET_MTIM) {
|
let time_to_set = if fst_flags.contains(Fstflags::SET_MTIM) {
|
||||||
@@ -87,7 +85,7 @@ pub fn path_filestat_set_times<M: MemorySize>(
|
|||||||
} else {
|
} else {
|
||||||
wasi_try!(get_current_time_in_nanos())
|
wasi_try!(get_current_time_in_nanos())
|
||||||
};
|
};
|
||||||
inode.stat.write().unwrap().st_mtim = time_to_set;
|
fd_inode.stat.write().unwrap().st_mtim = time_to_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
Errno::Success
|
Errno::Success
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ pub fn path_link<M: MemorySize>(
|
|||||||
debug!(" - will follow symlinks when opening path");
|
debug!(" - will follow symlinks when opening path");
|
||||||
}
|
}
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0);
|
let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
||||||
let mut old_path_str = unsafe { get_input_str!(&memory, old_path, old_path_len) };
|
let mut old_path_str = unsafe { get_input_str!(&memory, old_path, old_path_len) };
|
||||||
let mut new_path_str = unsafe { get_input_str!(&memory, new_path, new_path_len) };
|
let mut new_path_str = unsafe { get_input_str!(&memory, new_path, new_path_len) };
|
||||||
let source_fd = wasi_try!(state.fs.get_fd(old_fd));
|
let source_fd = wasi_try!(state.fs.get_fd(old_fd));
|
||||||
@@ -54,30 +54,28 @@ pub fn path_link<M: MemorySize>(
|
|||||||
new_path_str = ctx.data().state.fs.relative_path_to_absolute(new_path_str);
|
new_path_str = ctx.data().state.fs.relative_path_to_absolute(new_path_str);
|
||||||
|
|
||||||
let source_inode = wasi_try!(state.fs.get_inode_at_path(
|
let source_inode = wasi_try!(state.fs.get_inode_at_path(
|
||||||
inodes.deref_mut(),
|
inodes,
|
||||||
old_fd,
|
old_fd,
|
||||||
&old_path_str,
|
&old_path_str,
|
||||||
old_flags & __WASI_LOOKUP_SYMLINK_FOLLOW != 0,
|
old_flags & __WASI_LOOKUP_SYMLINK_FOLLOW != 0,
|
||||||
));
|
));
|
||||||
let target_path_arg = std::path::PathBuf::from(&new_path_str);
|
let target_path_arg = std::path::PathBuf::from(&new_path_str);
|
||||||
let (target_parent_inode, new_entry_name) = wasi_try!(state.fs.get_parent_inode_at_path(
|
let (target_parent_inode, new_entry_name) =
|
||||||
inodes.deref_mut(),
|
wasi_try!(state
|
||||||
new_fd,
|
.fs
|
||||||
&target_path_arg,
|
.get_parent_inode_at_path(inodes, new_fd, &target_path_arg, false));
|
||||||
false
|
|
||||||
));
|
|
||||||
|
|
||||||
if inodes.arena[source_inode].stat.write().unwrap().st_nlink == Linkcount::max_value() {
|
if source_inode.stat.write().unwrap().st_nlink == Linkcount::max_value() {
|
||||||
return Errno::Mlink;
|
return Errno::Mlink;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let mut guard = inodes.arena[target_parent_inode].write();
|
let mut guard = target_parent_inode.write();
|
||||||
match guard.deref_mut() {
|
match guard.deref_mut() {
|
||||||
Kind::Dir { entries, .. } => {
|
Kind::Dir { entries, .. } => {
|
||||||
if entries.contains_key(&new_entry_name) {
|
if entries.contains_key(&new_entry_name) {
|
||||||
return Errno::Exist;
|
return Errno::Exist;
|
||||||
}
|
}
|
||||||
entries.insert(new_entry_name, source_inode);
|
entries.insert(new_entry_name, source_inode.clone());
|
||||||
}
|
}
|
||||||
Kind::Root { .. } => return Errno::Inval,
|
Kind::Root { .. } => return Errno::Inval,
|
||||||
Kind::File { .. }
|
Kind::File { .. }
|
||||||
@@ -88,7 +86,7 @@ pub fn path_link<M: MemorySize>(
|
|||||||
| Kind::EventNotifications { .. } => return Errno::Notdir,
|
| Kind::EventNotifications { .. } => return Errno::Notdir,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inodes.arena[source_inode].stat.write().unwrap().st_nlink += 1;
|
source_inode.stat.write().unwrap().st_nlink += 1;
|
||||||
|
|
||||||
Errno::Success
|
Errno::Success
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ pub fn path_open<M: MemorySize>(
|
|||||||
debug!(" - will follow symlinks when opening path");
|
debug!(" - will follow symlinks when opening path");
|
||||||
}
|
}
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0);
|
let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
||||||
/* TODO: find actual upper bound on name size (also this is a path, not a name :think-fish:) */
|
/* TODO: find actual upper bound on name size (also this is a path, not a name :think-fish:) */
|
||||||
let path_len64: u64 = path_len.into();
|
let path_len64: u64 = path_len.into();
|
||||||
if path_len64 > 1024u64 * 1024u64 {
|
if path_len64 > 1024u64 * 1024u64 {
|
||||||
@@ -81,7 +81,7 @@ pub fn path_open<M: MemorySize>(
|
|||||||
|
|
||||||
let path_arg = std::path::PathBuf::from(&path_string);
|
let path_arg = std::path::PathBuf::from(&path_string);
|
||||||
let maybe_inode = state.fs.get_inode_at_path(
|
let maybe_inode = state.fs.get_inode_at_path(
|
||||||
inodes.deref_mut(),
|
inodes,
|
||||||
dirfd,
|
dirfd,
|
||||||
&path_string,
|
&path_string,
|
||||||
dirflags & __WASI_LOOKUP_SYMLINK_FOLLOW != 0,
|
dirflags & __WASI_LOOKUP_SYMLINK_FOLLOW != 0,
|
||||||
@@ -148,7 +148,9 @@ pub fn path_open<M: MemorySize>(
|
|||||||
|
|
||||||
let inode = if let Ok(inode) = maybe_inode {
|
let inode = if let Ok(inode) = maybe_inode {
|
||||||
// Happy path, we found the file we're trying to open
|
// Happy path, we found the file we're trying to open
|
||||||
let mut guard = inodes.arena[inode].write();
|
let processing_inode = inode.clone();
|
||||||
|
let mut guard = processing_inode.write();
|
||||||
|
|
||||||
let deref_mut = guard.deref_mut();
|
let deref_mut = guard.deref_mut();
|
||||||
match deref_mut {
|
match deref_mut {
|
||||||
Kind::File {
|
Kind::File {
|
||||||
@@ -244,13 +246,13 @@ pub fn path_open<M: MemorySize>(
|
|||||||
// strip end file name
|
// strip end file name
|
||||||
|
|
||||||
let (parent_inode, new_entity_name) = wasi_try!(state.fs.get_parent_inode_at_path(
|
let (parent_inode, new_entity_name) = wasi_try!(state.fs.get_parent_inode_at_path(
|
||||||
inodes.deref_mut(),
|
inodes,
|
||||||
dirfd,
|
dirfd,
|
||||||
&path_arg,
|
&path_arg,
|
||||||
dirflags & __WASI_LOOKUP_SYMLINK_FOLLOW != 0
|
dirflags & __WASI_LOOKUP_SYMLINK_FOLLOW != 0
|
||||||
));
|
));
|
||||||
let new_file_host_path = {
|
let new_file_host_path = {
|
||||||
let guard = inodes.arena[parent_inode].read();
|
let guard = parent_inode.read();
|
||||||
match guard.deref() {
|
match guard.deref() {
|
||||||
Kind::Dir { path, .. } => {
|
Kind::Dir { path, .. } => {
|
||||||
let mut new_path = path.clone();
|
let mut new_path = path.clone();
|
||||||
@@ -301,21 +303,18 @@ pub fn path_open<M: MemorySize>(
|
|||||||
path: new_file_host_path,
|
path: new_file_host_path,
|
||||||
fd: None,
|
fd: None,
|
||||||
};
|
};
|
||||||
wasi_try!(state.fs.create_inode(
|
wasi_try!(state
|
||||||
inodes.deref_mut(),
|
.fs
|
||||||
kind,
|
.create_inode(inodes, kind, false, new_entity_name.clone()))
|
||||||
false,
|
|
||||||
new_entity_name.clone()
|
|
||||||
))
|
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut guard = inodes.arena[parent_inode].write();
|
let mut guard = parent_inode.write();
|
||||||
if let Kind::Dir {
|
if let Kind::Dir {
|
||||||
ref mut entries, ..
|
ref mut entries, ..
|
||||||
} = guard.deref_mut()
|
} = guard.deref_mut()
|
||||||
{
|
{
|
||||||
entries.insert(new_entity_name, new_inode);
|
entries.insert(new_entity_name, new_inode.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ pub fn path_readlink<M: MemorySize>(
|
|||||||
ctx.data().tid()
|
ctx.data().tid()
|
||||||
);
|
);
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0);
|
let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
||||||
|
|
||||||
let base_dir = wasi_try!(state.fs.get_fd(dir_fd));
|
let base_dir = wasi_try!(state.fs.get_fd(dir_fd));
|
||||||
if !base_dir.rights.contains(Rights::PATH_READLINK) {
|
if !base_dir.rights.contains(Rights::PATH_READLINK) {
|
||||||
@@ -51,12 +51,10 @@ pub fn path_readlink<M: MemorySize>(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let inode = wasi_try!(state
|
let inode = wasi_try!(state.fs.get_inode_at_path(inodes, dir_fd, &path_str, false));
|
||||||
.fs
|
|
||||||
.get_inode_at_path(inodes.deref_mut(), dir_fd, &path_str, false));
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let guard = inodes.arena[inode].read();
|
let guard = inode.read();
|
||||||
if let Kind::Symlink { relative_path, .. } = guard.deref() {
|
if let Kind::Symlink { relative_path, .. } = guard.deref() {
|
||||||
let rel_path_str = relative_path.to_string_lossy();
|
let rel_path_str = relative_path.to_string_lossy();
|
||||||
debug!("Result => {:?}", rel_path_str);
|
debug!("Result => {:?}", rel_path_str);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ pub fn path_remove_directory<M: MemorySize>(
|
|||||||
ctx.data().tid()
|
ctx.data().tid()
|
||||||
);
|
);
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0);
|
let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
||||||
|
|
||||||
let base_dir = wasi_try!(state.fs.get_fd(fd));
|
let base_dir = wasi_try!(state.fs.get_fd(fd));
|
||||||
let mut path_str = unsafe { get_input_str!(&memory, path, path_len) };
|
let mut path_str = unsafe { get_input_str!(&memory, path, path_len) };
|
||||||
@@ -31,18 +31,16 @@ pub fn path_remove_directory<M: MemorySize>(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let inode = wasi_try!(state
|
let inode = wasi_try!(state.fs.get_inode_at_path(inodes, fd, &path_str, false));
|
||||||
.fs
|
|
||||||
.get_inode_at_path(inodes.deref_mut(), fd, &path_str, false));
|
|
||||||
let (parent_inode, childs_name) = wasi_try!(state.fs.get_parent_inode_at_path(
|
let (parent_inode, childs_name) = wasi_try!(state.fs.get_parent_inode_at_path(
|
||||||
inodes.deref_mut(),
|
inodes,
|
||||||
fd,
|
fd,
|
||||||
std::path::Path::new(&path_str),
|
std::path::Path::new(&path_str),
|
||||||
false
|
false
|
||||||
));
|
));
|
||||||
|
|
||||||
let host_path_to_remove = {
|
let host_path_to_remove = {
|
||||||
let guard = inodes.arena[inode].read();
|
let guard = inode.read();
|
||||||
match guard.deref() {
|
match guard.deref() {
|
||||||
Kind::Dir { entries, path, .. } => {
|
Kind::Dir { entries, path, .. } => {
|
||||||
if !entries.is_empty() || wasi_try!(state.fs_read_dir(path)).count() != 0 {
|
if !entries.is_empty() || wasi_try!(state.fs_read_dir(path)).count() != 0 {
|
||||||
@@ -56,14 +54,14 @@ pub fn path_remove_directory<M: MemorySize>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut guard = inodes.arena[parent_inode].write();
|
let mut guard = parent_inode.write();
|
||||||
match guard.deref_mut() {
|
match guard.deref_mut() {
|
||||||
Kind::Dir {
|
Kind::Dir {
|
||||||
ref mut entries, ..
|
ref mut entries, ..
|
||||||
} => {
|
} => {
|
||||||
let removed_inode = wasi_try!(entries.remove(&childs_name).ok_or(Errno::Inval));
|
let removed_inode = wasi_try!(entries.remove(&childs_name).ok_or(Errno::Inval));
|
||||||
// TODO: make this a debug assert in the future
|
// TODO: make this a debug assert in the future
|
||||||
assert!(inode == removed_inode);
|
assert!(inode.ino() == removed_inode.ino());
|
||||||
}
|
}
|
||||||
Kind::Root { .. } => return Errno::Access,
|
Kind::Root { .. } => return Errno::Access,
|
||||||
_ => unreachable!(
|
_ => unreachable!(
|
||||||
@@ -74,7 +72,7 @@ pub fn path_remove_directory<M: MemorySize>(
|
|||||||
|
|
||||||
if let Err(err) = state.fs_remove_dir(host_path_to_remove) {
|
if let Err(err) = state.fs_remove_dir(host_path_to_remove) {
|
||||||
// reinsert to prevent FS from being in bad state
|
// reinsert to prevent FS from being in bad state
|
||||||
let mut guard = inodes.arena[parent_inode].write();
|
let mut guard = parent_inode.write();
|
||||||
if let Kind::Dir {
|
if let Kind::Dir {
|
||||||
ref mut entries, ..
|
ref mut entries, ..
|
||||||
} = guard.deref_mut()
|
} = guard.deref_mut()
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ pub fn path_rename<M: MemorySize>(
|
|||||||
old_fd, new_fd
|
old_fd, new_fd
|
||||||
);
|
);
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0);
|
let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
||||||
let mut source_str = unsafe { get_input_str!(&memory, old_path, old_path_len) };
|
let mut source_str = unsafe { get_input_str!(&memory, old_path, old_path_len) };
|
||||||
source_str = ctx.data().state.fs.relative_path_to_absolute(source_str);
|
source_str = ctx.data().state.fs.relative_path_to_absolute(source_str);
|
||||||
let source_path = std::path::Path::new(&source_str);
|
let source_path = std::path::Path::new(&source_str);
|
||||||
@@ -52,29 +52,27 @@ pub fn path_rename<M: MemorySize>(
|
|||||||
|
|
||||||
// this is to be sure the source file is fetch from filesystem if needed
|
// this is to be sure the source file is fetch from filesystem if needed
|
||||||
wasi_try!(state.fs.get_inode_at_path(
|
wasi_try!(state.fs.get_inode_at_path(
|
||||||
inodes.deref_mut(),
|
inodes,
|
||||||
old_fd,
|
old_fd,
|
||||||
source_path.to_str().as_ref().unwrap(),
|
source_path.to_str().as_ref().unwrap(),
|
||||||
true
|
true
|
||||||
));
|
));
|
||||||
// Create the destination inode if the file exists.
|
// Create the destination inode if the file exists.
|
||||||
let _ = state.fs.get_inode_at_path(
|
let _ =
|
||||||
inodes.deref_mut(),
|
state
|
||||||
new_fd,
|
.fs
|
||||||
target_path.to_str().as_ref().unwrap(),
|
.get_inode_at_path(inodes, new_fd, target_path.to_str().as_ref().unwrap(), true);
|
||||||
true,
|
|
||||||
);
|
|
||||||
let (source_parent_inode, source_entry_name) =
|
let (source_parent_inode, source_entry_name) =
|
||||||
wasi_try!(state
|
wasi_try!(state
|
||||||
.fs
|
.fs
|
||||||
.get_parent_inode_at_path(inodes.deref_mut(), old_fd, source_path, true));
|
.get_parent_inode_at_path(inodes, old_fd, source_path, true));
|
||||||
let (target_parent_inode, target_entry_name) =
|
let (target_parent_inode, target_entry_name) =
|
||||||
wasi_try!(state
|
wasi_try!(state
|
||||||
.fs
|
.fs
|
||||||
.get_parent_inode_at_path(inodes.deref_mut(), new_fd, target_path, true));
|
.get_parent_inode_at_path(inodes, new_fd, target_path, true));
|
||||||
let mut need_create = true;
|
let mut need_create = true;
|
||||||
let host_adjusted_target_path = {
|
let host_adjusted_target_path = {
|
||||||
let guard = inodes.arena[target_parent_inode].read();
|
let guard = target_parent_inode.read();
|
||||||
match guard.deref() {
|
match guard.deref() {
|
||||||
Kind::Dir { entries, path, .. } => {
|
Kind::Dir { entries, path, .. } => {
|
||||||
if entries.contains_key(&target_entry_name) {
|
if entries.contains_key(&target_entry_name) {
|
||||||
@@ -96,7 +94,7 @@ pub fn path_rename<M: MemorySize>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let source_entry = {
|
let source_entry = {
|
||||||
let mut guard = inodes.arena[source_parent_inode].write();
|
let mut guard = source_parent_inode.write();
|
||||||
match guard.deref_mut() {
|
match guard.deref_mut() {
|
||||||
Kind::Dir { entries, .. } => {
|
Kind::Dir { entries, .. } => {
|
||||||
wasi_try!(entries.remove(&source_entry_name).ok_or(Errno::Noent))
|
wasi_try!(entries.remove(&source_entry_name).ok_or(Errno::Noent))
|
||||||
@@ -113,7 +111,7 @@ pub fn path_rename<M: MemorySize>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut guard = inodes.arena[source_entry].write();
|
let mut guard = source_entry.write();
|
||||||
match guard.deref_mut() {
|
match guard.deref_mut() {
|
||||||
Kind::File {
|
Kind::File {
|
||||||
handle, ref path, ..
|
handle, ref path, ..
|
||||||
@@ -131,7 +129,7 @@ pub fn path_rename<M: MemorySize>(
|
|||||||
drop(guard);
|
drop(guard);
|
||||||
let out = state.fs_rename(&path_clone, &host_adjusted_target_path);
|
let out = state.fs_rename(&path_clone, &host_adjusted_target_path);
|
||||||
{
|
{
|
||||||
let mut guard = inodes.arena[source_entry].write();
|
let mut guard = source_entry.write();
|
||||||
if let Kind::File { ref mut path, .. } = guard.deref_mut() {
|
if let Kind::File { ref mut path, .. } = guard.deref_mut() {
|
||||||
*path = host_adjusted_target_path;
|
*path = host_adjusted_target_path;
|
||||||
} else {
|
} else {
|
||||||
@@ -142,7 +140,7 @@ pub fn path_rename<M: MemorySize>(
|
|||||||
};
|
};
|
||||||
// if the above operation failed we have to revert the previous change and then fail
|
// if the above operation failed we have to revert the previous change and then fail
|
||||||
if let Err(e) = result {
|
if let Err(e) = result {
|
||||||
let mut guard = inodes.arena[source_parent_inode].write();
|
let mut guard = source_parent_inode.write();
|
||||||
if let Kind::Dir { entries, .. } = guard.deref_mut() {
|
if let Kind::Dir { entries, .. } = guard.deref_mut() {
|
||||||
entries.insert(source_entry_name, source_entry);
|
entries.insert(source_entry_name, source_entry);
|
||||||
return e;
|
return e;
|
||||||
@@ -156,7 +154,7 @@ pub fn path_rename<M: MemorySize>(
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
drop(guard);
|
drop(guard);
|
||||||
let mut guard = inodes.arena[source_entry].write();
|
let mut guard = source_entry.write();
|
||||||
if let Kind::Dir { path, .. } = guard.deref_mut() {
|
if let Kind::Dir { path, .. } = guard.deref_mut() {
|
||||||
*path = host_adjusted_target_path;
|
*path = host_adjusted_target_path;
|
||||||
}
|
}
|
||||||
@@ -172,7 +170,7 @@ pub fn path_rename<M: MemorySize>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if need_create {
|
if need_create {
|
||||||
let mut guard = inodes.arena[target_parent_inode].write();
|
let mut guard = target_parent_inode.write();
|
||||||
if let Kind::Dir { entries, .. } = guard.deref_mut() {
|
if let Kind::Dir { entries, .. } = guard.deref_mut() {
|
||||||
let result = entries.insert(target_entry_name, source_entry);
|
let result = entries.insert(target_entry_name, source_entry);
|
||||||
assert!(
|
assert!(
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ pub fn path_symlink<M: MemorySize>(
|
|||||||
ctx.data().tid()
|
ctx.data().tid()
|
||||||
);
|
);
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0);
|
let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
||||||
let mut old_path_str = unsafe { get_input_str!(&memory, old_path, old_path_len) };
|
let mut old_path_str = unsafe { get_input_str!(&memory, old_path, old_path_len) };
|
||||||
let mut new_path_str = unsafe { get_input_str!(&memory, new_path, new_path_len) };
|
let mut new_path_str = unsafe { get_input_str!(&memory, new_path, new_path_len) };
|
||||||
old_path_str = ctx.data().state.fs.relative_path_to_absolute(old_path_str);
|
old_path_str = ctx.data().state.fs.relative_path_to_absolute(old_path_str);
|
||||||
@@ -43,10 +43,8 @@ pub fn path_symlink<M: MemorySize>(
|
|||||||
let (source_inode, _) =
|
let (source_inode, _) =
|
||||||
wasi_try!(state
|
wasi_try!(state
|
||||||
.fs
|
.fs
|
||||||
.get_parent_inode_at_path(inodes.deref_mut(), fd, old_path_path, true));
|
.get_parent_inode_at_path(inodes, fd, old_path_path, true));
|
||||||
let depth = state
|
let depth = state.fs.path_depth_from_fd(fd, source_inode);
|
||||||
.fs
|
|
||||||
.path_depth_from_fd(inodes.deref(), fd, source_inode);
|
|
||||||
|
|
||||||
// depth == -1 means folder is not relative. See issue #3233.
|
// depth == -1 means folder is not relative. See issue #3233.
|
||||||
let depth = match depth {
|
let depth = match depth {
|
||||||
@@ -58,11 +56,11 @@ pub fn path_symlink<M: MemorySize>(
|
|||||||
let (target_parent_inode, entry_name) =
|
let (target_parent_inode, entry_name) =
|
||||||
wasi_try!(state
|
wasi_try!(state
|
||||||
.fs
|
.fs
|
||||||
.get_parent_inode_at_path(inodes.deref_mut(), fd, new_path_path, true));
|
.get_parent_inode_at_path(inodes, fd, new_path_path, true));
|
||||||
|
|
||||||
// short circuit if anything is wrong, before we create an inode
|
// short circuit if anything is wrong, before we create an inode
|
||||||
{
|
{
|
||||||
let guard = inodes.arena[target_parent_inode].read();
|
let guard = target_parent_inode.read();
|
||||||
match guard.deref() {
|
match guard.deref() {
|
||||||
Kind::Dir { entries, .. } => {
|
Kind::Dir { entries, .. } => {
|
||||||
if entries.contains_key(&entry_name) {
|
if entries.contains_key(&entry_name) {
|
||||||
@@ -96,15 +94,13 @@ pub fn path_symlink<M: MemorySize>(
|
|||||||
path_to_symlink: std::path::PathBuf::from(new_path_str),
|
path_to_symlink: std::path::PathBuf::from(new_path_str),
|
||||||
relative_path,
|
relative_path,
|
||||||
};
|
};
|
||||||
let new_inode = state.fs.create_inode_with_default_stat(
|
let new_inode =
|
||||||
inodes.deref_mut(),
|
state
|
||||||
kind,
|
.fs
|
||||||
false,
|
.create_inode_with_default_stat(inodes, kind, false, entry_name.clone().into());
|
||||||
entry_name.clone().into(),
|
|
||||||
);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut guard = inodes.arena[target_parent_inode].write();
|
let mut guard = target_parent_inode.write();
|
||||||
if let Kind::Dir {
|
if let Kind::Dir {
|
||||||
ref mut entries, ..
|
ref mut entries, ..
|
||||||
} = guard.deref_mut()
|
} = guard.deref_mut()
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ pub fn path_unlink_file<M: MemorySize>(
|
|||||||
ctx.data().tid()
|
ctx.data().tid()
|
||||||
);
|
);
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0);
|
let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
||||||
|
|
||||||
let base_dir = wasi_try!(state.fs.get_fd(fd));
|
let base_dir = wasi_try!(state.fs.get_fd(fd));
|
||||||
if !base_dir.rights.contains(Rights::PATH_UNLINK_FILE) {
|
if !base_dir.rights.contains(Rights::PATH_UNLINK_FILE) {
|
||||||
@@ -42,26 +42,24 @@ pub fn path_unlink_file<M: MemorySize>(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let inode = wasi_try!(state
|
let inode = wasi_try!(state.fs.get_inode_at_path(inodes, fd, &path_str, false));
|
||||||
.fs
|
|
||||||
.get_inode_at_path(inodes.deref_mut(), fd, &path_str, false));
|
|
||||||
let (parent_inode, childs_name) = wasi_try!(state.fs.get_parent_inode_at_path(
|
let (parent_inode, childs_name) = wasi_try!(state.fs.get_parent_inode_at_path(
|
||||||
inodes.deref_mut(),
|
inodes,
|
||||||
fd,
|
fd,
|
||||||
std::path::Path::new(&path_str),
|
std::path::Path::new(&path_str),
|
||||||
false
|
false
|
||||||
));
|
));
|
||||||
|
|
||||||
let removed_inode = {
|
let removed_inode = {
|
||||||
let mut guard = inodes.arena[parent_inode].write();
|
let mut guard = parent_inode.write();
|
||||||
match guard.deref_mut() {
|
match guard.deref_mut() {
|
||||||
Kind::Dir {
|
Kind::Dir {
|
||||||
ref mut entries, ..
|
ref mut entries, ..
|
||||||
} => {
|
} => {
|
||||||
let removed_inode = wasi_try!(entries.remove(&childs_name).ok_or(Errno::Inval));
|
let removed_inode = wasi_try!(entries.remove(&childs_name).ok_or(Errno::Inval));
|
||||||
// TODO: make this a debug assert in the future
|
// TODO: make this a debug assert in the future
|
||||||
assert!(inode == removed_inode);
|
assert!(inode.ino() == removed_inode.ino());
|
||||||
debug_assert!(inodes.arena[inode].stat.read().unwrap().st_nlink > 0);
|
debug_assert!(inode.stat.read().unwrap().st_nlink > 0);
|
||||||
removed_inode
|
removed_inode
|
||||||
}
|
}
|
||||||
Kind::Root { .. } => return Errno::Access,
|
Kind::Root { .. } => return Errno::Access,
|
||||||
@@ -72,13 +70,13 @@ pub fn path_unlink_file<M: MemorySize>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let st_nlink = {
|
let st_nlink = {
|
||||||
let mut guard = inodes.arena[removed_inode].stat.write().unwrap();
|
let mut guard = removed_inode.stat.write().unwrap();
|
||||||
guard.st_nlink -= 1;
|
guard.st_nlink -= 1;
|
||||||
guard.st_nlink
|
guard.st_nlink
|
||||||
};
|
};
|
||||||
if st_nlink == 0 {
|
if st_nlink == 0 {
|
||||||
{
|
{
|
||||||
let mut guard = inodes.arena[removed_inode].read();
|
let mut guard = removed_inode.read();
|
||||||
match guard.deref() {
|
match guard.deref() {
|
||||||
Kind::File { handle, path, .. } => {
|
Kind::File { handle, path, .. } => {
|
||||||
if let Some(h) = handle {
|
if let Some(h) = handle {
|
||||||
@@ -100,27 +98,6 @@ pub fn path_unlink_file<M: MemorySize>(
|
|||||||
_ => unimplemented!("wasi::path_unlink_file for Buffer"),
|
_ => unimplemented!("wasi::path_unlink_file for Buffer"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: test this on Windows and actually make it portable
|
|
||||||
// make the file an orphan fd if the fd is still open
|
|
||||||
let fd_is_orphaned = {
|
|
||||||
let guard = inodes.arena[removed_inode].read();
|
|
||||||
if let Kind::File { handle, .. } = guard.deref() {
|
|
||||||
handle.is_some()
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let removed_inode_val = unsafe { state.fs.remove_inode(inodes.deref_mut(), removed_inode) };
|
|
||||||
assert!(
|
|
||||||
removed_inode_val.is_some(),
|
|
||||||
"Inode could not be removed because it doesn't exist"
|
|
||||||
);
|
|
||||||
|
|
||||||
if fd_is_orphaned {
|
|
||||||
inodes
|
|
||||||
.orphan_fds
|
|
||||||
.insert(removed_inode, removed_inode_val.unwrap());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Errno::Success
|
Errno::Success
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use std::f32::consts::E;
|
||||||
|
|
||||||
use wasmer_wasi_types::wasi::SubscriptionClock;
|
use wasmer_wasi_types::wasi::SubscriptionClock;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -5,6 +7,7 @@ use crate::{
|
|||||||
fs::{InodeValFilePollGuard, InodeValFilePollGuardJoin},
|
fs::{InodeValFilePollGuard, InodeValFilePollGuardJoin},
|
||||||
state::PollEventSet,
|
state::PollEventSet,
|
||||||
syscalls::*,
|
syscalls::*,
|
||||||
|
WasiInodes,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// ### `poll_oneoff()`
|
/// ### `poll_oneoff()`
|
||||||
@@ -28,12 +31,15 @@ pub fn poll_oneoff<M: MemorySize>(
|
|||||||
) -> Result<Errno, WasiError> {
|
) -> Result<Errno, WasiError> {
|
||||||
wasi_try_ok!(WasiEnv::process_signals_and_exit(&mut ctx)?);
|
wasi_try_ok!(WasiEnv::process_signals_and_exit(&mut ctx)?);
|
||||||
|
|
||||||
|
ctx.data_mut().poll_seed += 1;
|
||||||
let mut env = ctx.data();
|
let mut env = ctx.data();
|
||||||
let mut memory = env.memory_view(&ctx);
|
let mut memory = env.memory_view(&ctx);
|
||||||
|
|
||||||
let subscription_array = wasi_try_mem_ok!(in_.slice(&memory, nsubscriptions));
|
let subscription_array = wasi_try_mem_ok!(in_.slice(&memory, nsubscriptions));
|
||||||
let mut subscriptions = Vec::with_capacity(subscription_array.len() as usize);
|
let mut subscriptions = Vec::with_capacity(subscription_array.len() as usize);
|
||||||
for sub in subscription_array.iter() {
|
for n in 0..subscription_array.len() {
|
||||||
|
let n = (n + env.poll_seed) % subscription_array.len();
|
||||||
|
let sub = subscription_array.index(n);
|
||||||
let s = wasi_try_mem_ok!(sub.read());
|
let s = wasi_try_mem_ok!(sub.read());
|
||||||
subscriptions.push((None, PollEventSet::default(), s));
|
subscriptions.push((None, PollEventSet::default(), s));
|
||||||
}
|
}
|
||||||
@@ -97,17 +103,18 @@ impl<'a> Future for PollBatch<'a> {
|
|||||||
let mut guard = Pin::new(join);
|
let mut guard = Pin::new(join);
|
||||||
match guard.poll(cx) {
|
match guard.poll(cx) {
|
||||||
Poll::Pending => {}
|
Poll::Pending => {}
|
||||||
Poll::Ready(evt) => {
|
Poll::Ready(e) => {
|
||||||
tracing::trace!(
|
for evt in e {
|
||||||
"wasi[{}:{}]::poll_oneoff triggered_fd (fd={}, userdata={}, type={:?})",
|
tracing::trace!(
|
||||||
pid,
|
"wasi[{}:{}]::poll_oneoff triggered_fd (fd={}, userdata={}, type={:?})",
|
||||||
tid,
|
pid,
|
||||||
fd,
|
tid,
|
||||||
evt.userdata,
|
fd,
|
||||||
evt.type_,
|
evt.userdata,
|
||||||
);
|
evt.type_,
|
||||||
evts.push(evt);
|
);
|
||||||
done = true;
|
evts.push(evt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,8 +254,6 @@ pub(crate) fn poll_oneoff_internal(
|
|||||||
let mut guards = {
|
let mut guards = {
|
||||||
// We start by building a list of files we are going to poll
|
// We start by building a list of files we are going to poll
|
||||||
// and open a read lock on them all
|
// and open a read lock on them all
|
||||||
let inodes = state.inodes.clone();
|
|
||||||
let inodes = inodes.read().unwrap();
|
|
||||||
let mut fd_guards = Vec::with_capacity(subs.len());
|
let mut fd_guards = Vec::with_capacity(subs.len());
|
||||||
|
|
||||||
#[allow(clippy::significant_drop_in_scrutinee)]
|
#[allow(clippy::significant_drop_in_scrutinee)]
|
||||||
@@ -256,20 +261,17 @@ pub(crate) fn poll_oneoff_internal(
|
|||||||
if let Some(fd) = fd {
|
if let Some(fd) = fd {
|
||||||
let wasi_file_ref = match fd {
|
let wasi_file_ref = match fd {
|
||||||
__WASI_STDERR_FILENO => {
|
__WASI_STDERR_FILENO => {
|
||||||
wasi_try_ok_ok!(inodes
|
wasi_try_ok_ok!(WasiInodes::stderr(&state.fs.fd_map)
|
||||||
.stderr(&state.fs.fd_map)
|
|
||||||
.map(|g| g.into_poll_guard(fd, peb, s))
|
.map(|g| g.into_poll_guard(fd, peb, s))
|
||||||
.map_err(fs_error_into_wasi_err))
|
.map_err(fs_error_into_wasi_err))
|
||||||
}
|
}
|
||||||
__WASI_STDIN_FILENO => {
|
__WASI_STDIN_FILENO => {
|
||||||
wasi_try_ok_ok!(inodes
|
wasi_try_ok_ok!(WasiInodes::stdin(&state.fs.fd_map)
|
||||||
.stdin(&state.fs.fd_map)
|
|
||||||
.map(|g| g.into_poll_guard(fd, peb, s))
|
.map(|g| g.into_poll_guard(fd, peb, s))
|
||||||
.map_err(fs_error_into_wasi_err))
|
.map_err(fs_error_into_wasi_err))
|
||||||
}
|
}
|
||||||
__WASI_STDOUT_FILENO => {
|
__WASI_STDOUT_FILENO => {
|
||||||
wasi_try_ok_ok!(inodes
|
wasi_try_ok_ok!(WasiInodes::stdout(&state.fs.fd_map)
|
||||||
.stdout(&state.fs.fd_map)
|
|
||||||
.map(|g| g.into_poll_guard(fd, peb, s))
|
.map(|g| g.into_poll_guard(fd, peb, s))
|
||||||
.map_err(fs_error_into_wasi_err))
|
.map_err(fs_error_into_wasi_err))
|
||||||
}
|
}
|
||||||
@@ -281,7 +283,7 @@ pub(crate) fn poll_oneoff_internal(
|
|||||||
let inode = fd_entry.inode;
|
let inode = fd_entry.inode;
|
||||||
|
|
||||||
{
|
{
|
||||||
let guard = inodes.arena[inode].read();
|
let guard = inode.read();
|
||||||
if let Some(guard) =
|
if let Some(guard) =
|
||||||
crate::fs::InodeValFilePollGuard::new(fd, peb, s, guard.deref())
|
crate::fs::InodeValFilePollGuard::new(fd, peb, s, guard.deref())
|
||||||
{
|
{
|
||||||
@@ -307,12 +309,16 @@ pub(crate) fn poll_oneoff_internal(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(time_to_sleep) = time_to_sleep.as_ref() {
|
if let Some(time_to_sleep) = time_to_sleep.as_ref() {
|
||||||
tracing::trace!(
|
if *time_to_sleep == Duration::ZERO {
|
||||||
"wasi[{}:{}]::poll_oneoff wait_for_timeout={}",
|
tracing::trace!("wasi[{}:{}]::poll_oneoff non_blocking", pid, tid,);
|
||||||
pid,
|
} else {
|
||||||
tid,
|
tracing::trace!(
|
||||||
time_to_sleep.as_millis()
|
"wasi[{}:{}]::poll_oneoff wait_for_timeout={}",
|
||||||
);
|
pid,
|
||||||
|
tid,
|
||||||
|
time_to_sleep.as_millis()
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
tracing::trace!("wasi[{}:{}]::poll_oneoff wait_for_infinite", pid, tid,);
|
tracing::trace!("wasi[{}:{}]::poll_oneoff wait_for_infinite", pid, tid,);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,11 +75,9 @@ pub fn bus_poll<M: MemorySize>(
|
|||||||
// Function that turns a buffer into a readable file handle
|
// Function that turns a buffer into a readable file handle
|
||||||
let buf_to_fd = {
|
let buf_to_fd = {
|
||||||
let state = env.state.clone();
|
let state = env.state.clone();
|
||||||
let inodes = state.inodes.clone();
|
|
||||||
move |data: Vec<u8>| -> Result<WasiFd, BusErrno> {
|
move |data: Vec<u8>| -> Result<WasiFd, BusErrno> {
|
||||||
let mut inodes = inodes.write().unwrap();
|
|
||||||
let inode = state.fs.create_inode_with_default_stat(
|
let inode = state.fs.create_inode_with_default_stat(
|
||||||
inodes.deref_mut(),
|
&state.inodes,
|
||||||
Kind::Buffer { buffer: data },
|
Kind::Buffer { buffer: data },
|
||||||
false,
|
false,
|
||||||
"bus".into(),
|
"bus".into(),
|
||||||
|
|||||||
@@ -16,20 +16,20 @@ pub fn fd_pipe<M: MemorySize>(
|
|||||||
trace!("wasi[{}:{}]::fd_pipe", ctx.data().pid(), ctx.data().tid());
|
trace!("wasi[{}:{}]::fd_pipe", ctx.data().pid(), ctx.data().tid());
|
||||||
|
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0);
|
let (memory, state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
||||||
|
|
||||||
let pipes = WasiBidirectionalPipePair::new();
|
let pipes = WasiBidirectionalPipePair::new();
|
||||||
let pipe1 = pipes.tx;
|
let pipe1 = pipes.tx;
|
||||||
let pipe2 = pipes.rx;
|
let pipe2 = pipes.rx;
|
||||||
|
|
||||||
let inode1 = state.fs.create_inode_with_default_stat(
|
let inode1 = state.fs.create_inode_with_default_stat(
|
||||||
inodes.deref_mut(),
|
inodes,
|
||||||
Kind::Pipe { pipe: pipe1 },
|
Kind::Pipe { pipe: pipe1 },
|
||||||
false,
|
false,
|
||||||
"pipe".to_string().into(),
|
"pipe".to_string().into(),
|
||||||
);
|
);
|
||||||
let inode2 = state.fs.create_inode_with_default_stat(
|
let inode2 = state.fs.create_inode_with_default_stat(
|
||||||
inodes.deref_mut(),
|
inodes,
|
||||||
Kind::Pipe { pipe: pipe2 },
|
Kind::Pipe { pipe: pipe2 },
|
||||||
false,
|
false,
|
||||||
"pipe".to_string().into(),
|
"pipe".to_string().into(),
|
||||||
|
|||||||
@@ -12,11 +12,9 @@ pub fn getcwd<M: MemorySize>(
|
|||||||
) -> Errno {
|
) -> Errno {
|
||||||
debug!("wasi[{}:{}]::getcwd", ctx.data().pid(), ctx.data().tid());
|
debug!("wasi[{}:{}]::getcwd", ctx.data().pid(), ctx.data().tid());
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (memory, mut state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0);
|
let (memory, mut state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
||||||
|
|
||||||
let (_, cur_dir) = wasi_try!(state
|
let (_, cur_dir) = wasi_try!(state.fs.get_current_dir(inodes, crate::VIRTUAL_ROOT_FD,));
|
||||||
.fs
|
|
||||||
.get_current_dir(inodes.deref_mut(), crate::VIRTUAL_ROOT_FD,));
|
|
||||||
trace!(
|
trace!(
|
||||||
"wasi[{}:{}]::getcwd(current_dir={})",
|
"wasi[{}:{}]::getcwd(current_dir={})",
|
||||||
ctx.data().pid(),
|
ctx.data().pid(),
|
||||||
|
|||||||
@@ -57,12 +57,8 @@ pub fn proc_exec<M: MemorySize>(
|
|||||||
|
|
||||||
// Get the current working directory
|
// Get the current working directory
|
||||||
let (_, cur_dir) = {
|
let (_, cur_dir) = {
|
||||||
let (memory, state, mut inodes) =
|
let (memory, state, inodes) = ctx.data().get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
||||||
ctx.data().get_memory_and_wasi_state_and_inodes_mut(&ctx, 0);
|
match state.fs.get_current_dir(inodes, crate::VIRTUAL_ROOT_FD) {
|
||||||
match state
|
|
||||||
.fs
|
|
||||||
.get_current_dir(inodes.deref_mut(), crate::VIRTUAL_ROOT_FD)
|
|
||||||
{
|
|
||||||
Ok(a) => a,
|
Ok(a) => a,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!("failed to create subprocess for fork - {}", err);
|
warn!("failed to create subprocess for fork - {}", err);
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ pub fn proc_spawn_internal(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(args) = args {
|
if let Some(args) = args {
|
||||||
let mut child_state = env.state.fork(true);
|
let mut child_state = env.state.fork();
|
||||||
child_state.args = args;
|
child_state.args = args;
|
||||||
child_env.state = Arc::new(child_state);
|
child_env.state = Arc::new(child_state);
|
||||||
}
|
}
|
||||||
@@ -148,8 +148,8 @@ pub fn proc_spawn_internal(
|
|||||||
|
|
||||||
// Replace the STDIO
|
// Replace the STDIO
|
||||||
let (stdin, stdout, stderr) = {
|
let (stdin, stdout, stderr) = {
|
||||||
let (_, child_state, mut child_inodes) =
|
let (_, child_state, child_inodes) =
|
||||||
child_env.get_memory_and_wasi_state_and_inodes_mut(&new_store, 0);
|
child_env.get_memory_and_wasi_state_and_inodes(&new_store, 0);
|
||||||
let mut conv_stdio_mode = |mode: WasiStdioMode, fd: WasiFd| -> Result<OptionFd, BusErrno> {
|
let mut conv_stdio_mode = |mode: WasiStdioMode, fd: WasiFd| -> Result<OptionFd, BusErrno> {
|
||||||
match mode {
|
match mode {
|
||||||
WasiStdioMode::Piped => {
|
WasiStdioMode::Piped => {
|
||||||
@@ -157,13 +157,13 @@ pub fn proc_spawn_internal(
|
|||||||
let pipe1 = pipes.rx;
|
let pipe1 = pipes.rx;
|
||||||
let pipe2 = pipes.tx;
|
let pipe2 = pipes.tx;
|
||||||
let inode1 = child_state.fs.create_inode_with_default_stat(
|
let inode1 = child_state.fs.create_inode_with_default_stat(
|
||||||
child_inodes.deref_mut(),
|
child_inodes,
|
||||||
Kind::Pipe { pipe: pipe1 },
|
Kind::Pipe { pipe: pipe1 },
|
||||||
false,
|
false,
|
||||||
"pipe".into(),
|
"pipe".into(),
|
||||||
);
|
);
|
||||||
let inode2 = child_state.fs.create_inode_with_default_stat(
|
let inode2 = child_state.fs.create_inode_with_default_stat(
|
||||||
child_inodes.deref_mut(),
|
child_inodes,
|
||||||
Kind::Pipe { pipe: pipe2 },
|
Kind::Pipe { pipe: pipe2 },
|
||||||
false,
|
false,
|
||||||
"pipe".into(),
|
"pipe".into(),
|
||||||
@@ -198,7 +198,7 @@ pub fn proc_spawn_internal(
|
|||||||
fd: u32::MAX,
|
fd: u32::MAX,
|
||||||
}),
|
}),
|
||||||
_ => {
|
_ => {
|
||||||
child_state.fs.close_fd(child_inodes.deref(), fd);
|
child_state.fs.close_fd(fd);
|
||||||
Ok(OptionFd {
|
Ok(OptionFd {
|
||||||
tag: OptionTag::None,
|
tag: OptionTag::None,
|
||||||
fd: u32::MAX,
|
fd: u32::MAX,
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ pub fn sock_accept<M: MemorySize>(
|
|||||||
));
|
));
|
||||||
|
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0);
|
let (memory, state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
||||||
|
|
||||||
let kind = Kind::Socket {
|
let kind = Kind::Socket {
|
||||||
socket: InodeSocket::new(InodeSocketKind::TcpStream {
|
socket: InodeSocket::new(InodeSocketKind::TcpStream {
|
||||||
@@ -56,10 +56,9 @@ pub fn sock_accept<M: MemorySize>(
|
|||||||
read_timeout: None,
|
read_timeout: None,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
let inode =
|
let inode = state
|
||||||
state
|
.fs
|
||||||
.fs
|
.create_inode_with_default_stat(inodes, kind, false, "socket".into());
|
||||||
.create_inode_with_default_stat(inodes.deref_mut(), kind, false, "socket".into());
|
|
||||||
|
|
||||||
let mut new_flags = Fdflags::empty();
|
let mut new_flags = Fdflags::empty();
|
||||||
if fd_flags.contains(Fdflags::NONBLOCK) {
|
if fd_flags.contains(Fdflags::NONBLOCK) {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ pub fn sock_open<M: MemorySize>(
|
|||||||
debug!("wasi[{}:{}]::sock_open", ctx.data().pid(), ctx.data().tid());
|
debug!("wasi[{}:{}]::sock_open", ctx.data().pid(), ctx.data().tid());
|
||||||
|
|
||||||
let env = ctx.data();
|
let env = ctx.data();
|
||||||
let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0);
|
let (memory, state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
||||||
|
|
||||||
let kind = match ty {
|
let kind = match ty {
|
||||||
Socktype::Stream | Socktype::Dgram => Kind::Socket {
|
Socktype::Stream | Socktype::Dgram => Kind::Socket {
|
||||||
@@ -53,12 +53,10 @@ pub fn sock_open<M: MemorySize>(
|
|||||||
_ => return Errno::Notsup,
|
_ => return Errno::Notsup,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inode = state.fs.create_inode_with_default_stat(
|
let inode =
|
||||||
inodes.deref_mut(),
|
state
|
||||||
kind,
|
.fs
|
||||||
false,
|
.create_inode_with_default_stat(inodes, kind, false, "socket".to_string().into());
|
||||||
"socket".to_string().into(),
|
|
||||||
);
|
|
||||||
let rights = Rights::all_socket();
|
let rights = Rights::all_socket();
|
||||||
let fd = wasi_try!(state
|
let fd = wasi_try!(state
|
||||||
.fs
|
.fs
|
||||||
|
|||||||
@@ -25,27 +25,101 @@ pub fn sock_recv<M: MemorySize>(
|
|||||||
ro_data_len: WasmPtr<M::Offset, M>,
|
ro_data_len: WasmPtr<M::Offset, M>,
|
||||||
ro_flags: WasmPtr<RoFlags, M>,
|
ro_flags: WasmPtr<RoFlags, M>,
|
||||||
) -> Result<Errno, WasiError> {
|
) -> Result<Errno, WasiError> {
|
||||||
wasi_try_ok!(WasiEnv::process_signals_and_exit(&mut ctx)?);
|
let pid = ctx.data().pid();
|
||||||
|
let tid = ctx.data().tid();
|
||||||
|
|
||||||
|
let res = sock_recv_internal::<M>(
|
||||||
|
&mut ctx,
|
||||||
|
sock,
|
||||||
|
ri_data,
|
||||||
|
ri_data_len,
|
||||||
|
ri_flags,
|
||||||
|
ro_data_len,
|
||||||
|
ro_flags,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let mut ret = Errno::Success;
|
||||||
|
let bytes_read = match res {
|
||||||
|
Ok(bytes_read) => {
|
||||||
|
debug!(
|
||||||
|
%bytes_read,
|
||||||
|
"wasi[{}:{}]::sock_recv (fd={}, flags={:?})",
|
||||||
|
ctx.data().pid(),
|
||||||
|
ctx.data().tid(),
|
||||||
|
sock,
|
||||||
|
ri_flags
|
||||||
|
);
|
||||||
|
bytes_read
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
let socket_err = err.name();
|
||||||
|
debug!(
|
||||||
|
%socket_err,
|
||||||
|
"wasi[{}:{}]::sock_recv (fd={}, flags={:?})",
|
||||||
|
ctx.data().pid(),
|
||||||
|
ctx.data().tid(),
|
||||||
|
sock,
|
||||||
|
ri_flags
|
||||||
|
);
|
||||||
|
ret = err;
|
||||||
|
0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let env = ctx.data();
|
||||||
|
let memory = env.memory_view(&ctx);
|
||||||
|
|
||||||
|
let bytes_read: M::Offset = wasi_try_ok!(bytes_read.try_into().map_err(|_| Errno::Overflow));
|
||||||
|
wasi_try_mem_ok!(ro_flags.write(&memory, 0));
|
||||||
|
wasi_try_mem_ok!(ro_data_len.write(&memory, bytes_read));
|
||||||
|
|
||||||
|
Ok(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ### `sock_recv()`
|
||||||
|
/// Receive a message from a socket.
|
||||||
|
/// Note: This is similar to `recv` in POSIX, though it also supports reading
|
||||||
|
/// the data into multiple buffers in the manner of `readv`.
|
||||||
|
///
|
||||||
|
/// ## Parameters
|
||||||
|
///
|
||||||
|
/// * `ri_data` - List of scatter/gather vectors to which to store data.
|
||||||
|
/// * `ri_flags` - Message flags.
|
||||||
|
///
|
||||||
|
/// ## Return
|
||||||
|
///
|
||||||
|
/// Number of bytes stored in ri_data and message flags.
|
||||||
|
fn sock_recv_internal<M: MemorySize>(
|
||||||
|
ctx: &mut FunctionEnvMut<'_, WasiEnv>,
|
||||||
|
sock: WasiFd,
|
||||||
|
ri_data: WasmPtr<__wasi_iovec_t<M>, M>,
|
||||||
|
ri_data_len: M::Offset,
|
||||||
|
ri_flags: RiFlags,
|
||||||
|
ro_data_len: WasmPtr<M::Offset, M>,
|
||||||
|
ro_flags: WasmPtr<RoFlags, M>,
|
||||||
|
) -> Result<Result<usize, Errno>, WasiError> {
|
||||||
|
wasi_try_ok_ok!(WasiEnv::process_signals_and_exit(ctx)?);
|
||||||
|
|
||||||
let mut env = ctx.data();
|
let mut env = ctx.data();
|
||||||
let memory = env.memory_view(&ctx);
|
let memory = env.memory_view(ctx);
|
||||||
let iovs_arr = wasi_try_mem_ok!(ri_data.slice(&memory, ri_data_len));
|
let iovs_arr = wasi_try_mem_ok_ok!(ri_data.slice(&memory, ri_data_len));
|
||||||
|
|
||||||
let max_size = {
|
let max_size = {
|
||||||
let mut max_size = 0usize;
|
let mut max_size = 0usize;
|
||||||
for iovs in iovs_arr.iter() {
|
for iovs in iovs_arr.iter() {
|
||||||
let iovs = wasi_try_mem_ok!(iovs.read());
|
let iovs = wasi_try_mem_ok_ok!(iovs.read());
|
||||||
let buf_len: usize = wasi_try_ok!(iovs.buf_len.try_into().map_err(|_| Errno::Overflow));
|
let buf_len: usize =
|
||||||
|
wasi_try_ok_ok!(iovs.buf_len.try_into().map_err(|_| Errno::Overflow));
|
||||||
max_size += buf_len;
|
max_size += buf_len;
|
||||||
}
|
}
|
||||||
max_size
|
max_size
|
||||||
};
|
};
|
||||||
|
|
||||||
let bytes_read = {
|
let res = {
|
||||||
if max_size <= 10240 {
|
if max_size <= 10240 {
|
||||||
let mut buf: [MaybeUninit<u8>; 10240] = unsafe { MaybeUninit::uninit().assume_init() };
|
let mut buf: [MaybeUninit<u8>; 10240] = unsafe { MaybeUninit::uninit().assume_init() };
|
||||||
let writer = &mut buf[..max_size];
|
let writer = &mut buf[..max_size];
|
||||||
let amt = wasi_try_ok!(__sock_asyncify(
|
let amt = wasi_try_ok_ok!(__sock_asyncify(
|
||||||
env,
|
env,
|
||||||
sock,
|
sock,
|
||||||
Rights::SOCK_RECV,
|
Rights::SOCK_RECV,
|
||||||
@@ -55,12 +129,12 @@ pub fn sock_recv<M: MemorySize>(
|
|||||||
if amt > 0 {
|
if amt > 0 {
|
||||||
let buf: &[MaybeUninit<u8>] = &buf[..amt];
|
let buf: &[MaybeUninit<u8>] = &buf[..amt];
|
||||||
let buf: &[u8] = unsafe { std::mem::transmute(buf) };
|
let buf: &[u8] = unsafe { std::mem::transmute(buf) };
|
||||||
wasi_try_ok!(copy_from_slice(buf, &memory, iovs_arr).map(|_| amt))
|
copy_from_slice(buf, &memory, iovs_arr).map(|_| amt)
|
||||||
} else {
|
} else {
|
||||||
0
|
Ok(0)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let data = wasi_try_ok!(__sock_asyncify(
|
let data = wasi_try_ok_ok!(__sock_asyncify(
|
||||||
env,
|
env,
|
||||||
sock,
|
sock,
|
||||||
Rights::SOCK_RECV,
|
Rights::SOCK_RECV,
|
||||||
@@ -85,25 +159,12 @@ pub fn sock_recv<M: MemorySize>(
|
|||||||
let data_len = data.len();
|
let data_len = data.len();
|
||||||
if data_len > 0 {
|
if data_len > 0 {
|
||||||
let mut reader = &data[..];
|
let mut reader = &data[..];
|
||||||
wasi_try_ok!(read_bytes(reader, &memory, iovs_arr).map(|_| data_len))
|
read_bytes(reader, &memory, iovs_arr).map(|_| data_len)
|
||||||
} else {
|
} else {
|
||||||
0
|
Ok(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!(
|
Ok(res)
|
||||||
"wasi[{}:{}]::sock_recv (fd={}, read={}, flags={:?})",
|
|
||||||
ctx.data().pid(),
|
|
||||||
ctx.data().tid(),
|
|
||||||
sock,
|
|
||||||
bytes_read,
|
|
||||||
ri_flags
|
|
||||||
);
|
|
||||||
|
|
||||||
let bytes_read: M::Offset = wasi_try_ok!(bytes_read.try_into().map_err(|_| Errno::Overflow));
|
|
||||||
wasi_try_mem_ok!(ro_flags.write(&memory, 0));
|
|
||||||
wasi_try_mem_ok!(ro_data_len.write(&memory, bytes_read));
|
|
||||||
|
|
||||||
Ok(Errno::Success)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,17 +36,9 @@ pub fn sock_send<M: MemorySize>(
|
|||||||
.map(|a| a.buf_len)
|
.map(|a| a.buf_len)
|
||||||
.sum()
|
.sum()
|
||||||
};
|
};
|
||||||
debug!(
|
let buf_len: usize = wasi_try_ok!(buf_len.try_into().map_err(|_| Errno::Overflow));
|
||||||
"wasi[{}:{}]::sock_send (fd={}, buf_len={}, flags={:?})",
|
|
||||||
ctx.data().pid(),
|
|
||||||
ctx.data().tid(),
|
|
||||||
sock,
|
|
||||||
buf_len,
|
|
||||||
si_flags
|
|
||||||
);
|
|
||||||
let buf_len: usize = wasi_try_ok!(buf_len.try_into().map_err(|_| Errno::Inval));
|
|
||||||
|
|
||||||
let bytes_written = {
|
let res = {
|
||||||
if buf_len <= 10240 {
|
if buf_len <= 10240 {
|
||||||
let mut buf: [MaybeUninit<u8>; 10240] = unsafe { MaybeUninit::uninit().assume_init() };
|
let mut buf: [MaybeUninit<u8>; 10240] = unsafe { MaybeUninit::uninit().assume_init() };
|
||||||
let writer = &mut buf[..buf_len];
|
let writer = &mut buf[..buf_len];
|
||||||
@@ -55,23 +47,47 @@ pub fn sock_send<M: MemorySize>(
|
|||||||
let reader = &buf[..written];
|
let reader = &buf[..written];
|
||||||
let reader: &[u8] = unsafe { std::mem::transmute(reader) };
|
let reader: &[u8] = unsafe { std::mem::transmute(reader) };
|
||||||
|
|
||||||
wasi_try_ok!(__sock_asyncify(
|
__sock_asyncify(env, sock, Rights::SOCK_SEND, |socket, fd| async move {
|
||||||
env,
|
socket.send(env.tasks.deref(), reader, fd.flags).await
|
||||||
sock,
|
})
|
||||||
Rights::SOCK_SEND,
|
|
||||||
|socket, fd| async move { socket.send(env.tasks.deref(), reader, fd.flags).await },
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
let mut buf = Vec::with_capacity(buf_len);
|
let mut buf = Vec::with_capacity(buf_len);
|
||||||
wasi_try_ok!(write_bytes(&mut buf, &memory, iovs_arr));
|
wasi_try_ok!(write_bytes(&mut buf, &memory, iovs_arr));
|
||||||
|
|
||||||
let reader = &buf;
|
let reader = &buf;
|
||||||
wasi_try_ok!(__sock_asyncify(
|
__sock_asyncify(env, sock, Rights::SOCK_SEND, |socket, fd| async move {
|
||||||
env,
|
socket.send(env.tasks.deref(), reader, fd.flags).await
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut ret = Errno::Success;
|
||||||
|
let bytes_written = match res {
|
||||||
|
Ok(bytes_written) => {
|
||||||
|
debug!(
|
||||||
|
%bytes_written,
|
||||||
|
"wasi[{}:{}]::sock_send (fd={}, buf_len={}, flags={:?})",
|
||||||
|
ctx.data().pid(),
|
||||||
|
ctx.data().tid(),
|
||||||
sock,
|
sock,
|
||||||
Rights::SOCK_SEND,
|
buf_len,
|
||||||
|socket, fd| async move { socket.send(env.tasks.deref(), reader, fd.flags).await },
|
si_flags
|
||||||
))
|
);
|
||||||
|
bytes_written
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
let socket_err = err.name();
|
||||||
|
debug!(
|
||||||
|
%socket_err,
|
||||||
|
"wasi[{}:{}]::sock_send (fd={}, buf_len={}, flags={:?})",
|
||||||
|
ctx.data().pid(),
|
||||||
|
ctx.data().tid(),
|
||||||
|
sock,
|
||||||
|
buf_len,
|
||||||
|
si_flags
|
||||||
|
);
|
||||||
|
ret = err;
|
||||||
|
0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -79,5 +95,5 @@ pub fn sock_send<M: MemorySize>(
|
|||||||
wasi_try_ok!(bytes_written.try_into().map_err(|_| Errno::Overflow));
|
wasi_try_ok!(bytes_written.try_into().map_err(|_| Errno::Overflow));
|
||||||
wasi_try_mem_ok!(ret_data_len.write(&memory, bytes_written));
|
wasi_try_mem_ok!(ret_data_len.write(&memory, bytes_written));
|
||||||
|
|
||||||
Ok(Errno::Success)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use wasmer_vfs::AsyncReadExt;
|
use wasmer_vfs::AsyncReadExt;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::syscalls::*;
|
use crate::{syscalls::*, WasiInodes};
|
||||||
|
|
||||||
/// ### `sock_send_file()`
|
/// ### `sock_send_file()`
|
||||||
/// Sends the entire contents of a file down a socket
|
/// Sends the entire contents of a file down a socket
|
||||||
@@ -56,13 +56,11 @@ pub fn sock_send_file<M: MemorySize>(
|
|||||||
let fd_flags = fd_entry.flags;
|
let fd_flags = fd_entry.flags;
|
||||||
|
|
||||||
let data = {
|
let data = {
|
||||||
let inodes = env.state.inodes.clone();
|
|
||||||
match in_fd {
|
match in_fd {
|
||||||
__WASI_STDIN_FILENO => {
|
__WASI_STDIN_FILENO => {
|
||||||
let inodes = inodes.read().unwrap();
|
let mut stdin =
|
||||||
let mut stdin = wasi_try_ok!(inodes
|
wasi_try_ok!(WasiInodes::stdin_mut(&state.fs.fd_map)
|
||||||
.stdin_mut(&state.fs.fd_map)
|
.map_err(fs_error_into_wasi_err));
|
||||||
.map_err(fs_error_into_wasi_err));
|
|
||||||
let data = wasi_try_ok!(__asyncify(&mut ctx, None, async move {
|
let data = wasi_try_ok!(__asyncify(&mut ctx, None, async move {
|
||||||
// TODO: optimize with MaybeUninit
|
// TODO: optimize with MaybeUninit
|
||||||
let mut buf = vec![0u8; sub_count as usize];
|
let mut buf = vec![0u8; sub_count as usize];
|
||||||
@@ -81,10 +79,7 @@ pub fn sock_send_file<M: MemorySize>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let offset = fd_entry.offset.load(Ordering::Acquire) as usize;
|
let offset = fd_entry.offset.load(Ordering::Acquire) as usize;
|
||||||
let inode_idx = fd_entry.inode;
|
let inode = fd_entry.inode;
|
||||||
let inodes = inodes.read().unwrap();
|
|
||||||
let inode = &inodes.arena[inode_idx];
|
|
||||||
|
|
||||||
let data = {
|
let data = {
|
||||||
let mut guard = inode.write();
|
let mut guard = inode.write();
|
||||||
match guard.deref_mut() {
|
match guard.deref_mut() {
|
||||||
@@ -116,7 +111,6 @@ pub fn sock_send_file<M: MemorySize>(
|
|||||||
let socket = socket.clone();
|
let socket = socket.clone();
|
||||||
let tasks = tasks.clone();
|
let tasks = tasks.clone();
|
||||||
drop(guard);
|
drop(guard);
|
||||||
drop(inodes);
|
|
||||||
|
|
||||||
let data = wasi_try_ok!(__asyncify(&mut ctx, None, async {
|
let data = wasi_try_ok!(__asyncify(&mut ctx, None, async {
|
||||||
let mut buf = Vec::with_capacity(sub_count as usize);
|
let mut buf = Vec::with_capacity(sub_count as usize);
|
||||||
|
|||||||
@@ -144,13 +144,35 @@ pub fn thread_spawn<M: MemorySize>(
|
|||||||
|
|
||||||
let mut ret = Errno::Success;
|
let mut ret = Errno::Success;
|
||||||
if let Err(err) = spawn.call(store, user_data_low as i32, user_data_high as i32) {
|
if let Err(err) = spawn.call(store, user_data_low as i32, user_data_high as i32) {
|
||||||
debug!(
|
match err.downcast::<WasiError>() {
|
||||||
"wasi[{}:{}]::thread_spawn - thread failed - start: {}",
|
Ok(WasiError::Exit(0)) => ret = Errno::Success,
|
||||||
ctx.data(&store).pid(),
|
Ok(WasiError::Exit(code)) => {
|
||||||
ctx.data(&store).tid(),
|
debug!(
|
||||||
err
|
%code,
|
||||||
);
|
"wasi[{}:{}]::thread_spawn - thread exited",
|
||||||
ret = Errno::Noexec;
|
ctx.data(&store).pid(),
|
||||||
|
ctx.data(&store).tid(),
|
||||||
|
);
|
||||||
|
ret = Errno::Noexec;
|
||||||
|
}
|
||||||
|
Ok(WasiError::UnknownWasiVersion) => {
|
||||||
|
debug!(
|
||||||
|
"wasi[{}:{}]::thread_spawn - thread failed as wasi version is unknown",
|
||||||
|
ctx.data(&store).pid(),
|
||||||
|
ctx.data(&store).tid(),
|
||||||
|
);
|
||||||
|
ret = Errno::Noexec;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
debug!(
|
||||||
|
"wasi[{}:{}]::thread_spawn - thread failed with runtime error: {}",
|
||||||
|
ctx.data(&store).pid(),
|
||||||
|
ctx.data(&store).tid(),
|
||||||
|
err
|
||||||
|
);
|
||||||
|
ret = Errno::Noexec;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
trace!(
|
trace!(
|
||||||
"wasi[{}:{}]::thread_spawn - thread callback finished (reactor={:?}, ret={})",
|
"wasi[{}:{}]::thread_spawn - thread callback finished (reactor={:?}, ret={})",
|
||||||
|
|||||||
@@ -35,16 +35,15 @@ pub fn ws_connect<M: MemorySize>(
|
|||||||
})?);
|
})?);
|
||||||
env = ctx.data();
|
env = ctx.data();
|
||||||
|
|
||||||
let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0);
|
let (memory, state, inodes) = env.get_memory_and_wasi_state_and_inodes(&ctx, 0);
|
||||||
|
|
||||||
let kind = Kind::Socket {
|
let kind = Kind::Socket {
|
||||||
socket: InodeSocket::new(InodeSocketKind::WebSocket(socket)),
|
socket: InodeSocket::new(InodeSocketKind::WebSocket(socket)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let inode =
|
let inode = state
|
||||||
state
|
.fs
|
||||||
.fs
|
.create_inode_with_default_stat(inodes, kind, false, "socket".into());
|
||||||
.create_inode_with_default_stat(inodes.deref_mut(), kind, false, "socket".into());
|
|
||||||
let rights = Rights::all_socket();
|
let rights = Rights::all_socket();
|
||||||
let fd = wasi_try_ok!(state
|
let fd = wasi_try_ok!(state
|
||||||
.fs
|
.fs
|
||||||
|
|||||||
Reference in New Issue
Block a user