This reverst buggy commit e1e08f44b7
This commit is contained in:
Syrus Akbary
2022-11-21 11:09:19 -08:00
parent 71a27617ce
commit 0a1a71fd6e
16 changed files with 197 additions and 1269 deletions

4
Cargo.lock generated
View File

@@ -4195,9 +4195,9 @@ dependencies = [
[[package]] [[package]]
name = "wasmer-inline-c" name = "wasmer-inline-c"
version = "0.1.2" version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c4e7a2a3363ceeb2ee60371af9460748f2bf53569b58627f1f640284ab07778" checksum = "e2405c99de49dc05338e5ed2eb397fe70b7128340d960507d0ba716f7d29a91a"
dependencies = [ dependencies = [
"assert_cmd", "assert_cmd",
"cc", "cc",

View File

@@ -14,7 +14,7 @@
use std::io::{Read, Write}; use std::io::{Read, Write};
use wasmer::{Instance, Module, Store}; use wasmer::{Instance, Module, Store};
use wasmer_compiler_cranelift::Cranelift; use wasmer_compiler_cranelift::Cranelift;
use wasmer_wasi::{WasiBidirectionalSharedPipePair, WasiState}; use wasmer_wasi::{Pipe, WasiState};
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
let wasm_path = concat!( let wasm_path = concat!(
@@ -36,8 +36,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Creating `WasiEnv`..."); println!("Creating `WasiEnv`...");
// First, we create the `WasiEnv` with the stdio pipes // First, we create the `WasiEnv` with the stdio pipes
let mut input = WasiBidirectionalSharedPipePair::new().with_blocking(false); let mut input = Pipe::new();
let mut output = WasiBidirectionalSharedPipePair::new().with_blocking(false); let mut output = Pipe::new();
let wasi_env = WasiState::new("hello") let wasi_env = WasiState::new("hello")
.stdin(Box::new(input.clone())) .stdin(Box::new(input.clone()))
.stdout(Box::new(output.clone())) .stdout(Box::new(output.clone()))

View File

@@ -210,25 +210,28 @@ fn memory_grow() -> Result<(), String> {
fn function_new() -> Result<(), String> { fn function_new() -> Result<(), String> {
let mut store = Store::default(); let mut store = Store::default();
let function = Function::new_typed(&mut store, || {}); let function = Function::new_typed(&mut store, || {});
assert_eq!(function.ty(&mut store), FunctionType::new(vec![], vec![])); assert_eq!(
function.ty(&mut store).clone(),
FunctionType::new(vec![], vec![])
);
let function = Function::new_typed(&mut store, |_a: i32| {}); let function = Function::new_typed(&mut store, |_a: i32| {});
assert_eq!( assert_eq!(
function.ty(&mut store), function.ty(&mut store).clone(),
FunctionType::new(vec![Type::I32], vec![]) FunctionType::new(vec![Type::I32], vec![])
); );
let function = Function::new_typed(&mut store, |_a: i32, _b: i64, _c: f32, _d: f64| {}); let function = Function::new_typed(&mut store, |_a: i32, _b: i64, _c: f32, _d: f64| {});
assert_eq!( assert_eq!(
function.ty(&mut store), function.ty(&mut store).clone(),
FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![])
); );
let function = Function::new_typed(&mut store, || -> i32 { 1 }); let function = Function::new_typed(&mut store, || -> i32 { 1 });
assert_eq!( assert_eq!(
function.ty(&mut store), function.ty(&mut store).clone(),
FunctionType::new(vec![], vec![Type::I32]) FunctionType::new(vec![], vec![Type::I32])
); );
let function = Function::new_typed(&mut store, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }); let function = Function::new_typed(&mut store, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) });
assert_eq!( assert_eq!(
function.ty(&mut store), function.ty(&mut store).clone(),
FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64])
); );
Ok(()) Ok(())
@@ -243,11 +246,14 @@ fn function_new_env() -> Result<(), String> {
let my_env = MyEnv {}; let my_env = MyEnv {};
let env = FunctionEnv::new(&mut store, my_env); let env = FunctionEnv::new(&mut store, my_env);
let function = Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut<MyEnv>| {}); let function = Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut<MyEnv>| {});
assert_eq!(function.ty(&mut store), FunctionType::new(vec![], vec![])); assert_eq!(
function.ty(&mut store).clone(),
FunctionType::new(vec![], vec![])
);
let function = let function =
Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut<MyEnv>, _a: i32| {}); Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut<MyEnv>, _a: i32| {});
assert_eq!( assert_eq!(
function.ty(&mut store), function.ty(&mut store).clone(),
FunctionType::new(vec![Type::I32], vec![]) FunctionType::new(vec![Type::I32], vec![])
); );
let function = Function::new_typed_with_env( let function = Function::new_typed_with_env(
@@ -256,13 +262,13 @@ fn function_new_env() -> Result<(), String> {
|_env: FunctionEnvMut<MyEnv>, _a: i32, _b: i64, _c: f32, _d: f64| {}, |_env: FunctionEnvMut<MyEnv>, _a: i32, _b: i64, _c: f32, _d: f64| {},
); );
assert_eq!( assert_eq!(
function.ty(&mut store), function.ty(&mut store).clone(),
FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![])
); );
let function = let function =
Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut<MyEnv>| -> i32 { 1 }); Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut<MyEnv>| -> i32 { 1 });
assert_eq!( assert_eq!(
function.ty(&mut store), function.ty(&mut store).clone(),
FunctionType::new(vec![], vec![Type::I32]) FunctionType::new(vec![], vec![Type::I32])
); );
let function = Function::new_typed_with_env( let function = Function::new_typed_with_env(
@@ -271,7 +277,7 @@ fn function_new_env() -> Result<(), String> {
|_env: FunctionEnvMut<MyEnv>| -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }, |_env: FunctionEnvMut<MyEnv>| -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) },
); );
assert_eq!( assert_eq!(
function.ty(&mut store), function.ty(&mut store).clone(),
FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64])
); );
Ok(()) Ok(())
@@ -288,35 +294,35 @@ fn function_new_dynamic() -> Result<(), String> {
&function_type, &function_type,
|_values: &[Value]| unimplemented!(), |_values: &[Value]| unimplemented!(),
); );
assert_eq!(function.ty(&mut store), function_type); assert_eq!(function.ty(&mut store).clone(), function_type);
let function_type = FunctionType::new(vec![Type::I32], vec![]); let function_type = FunctionType::new(vec![Type::I32], vec![]);
let function = Function::new( let function = Function::new(
&mut store, &mut store,
&function_type, &function_type,
|_values: &[Value]| unimplemented!(), |_values: &[Value]| unimplemented!(),
); );
assert_eq!(function.ty(&mut store), function_type); assert_eq!(function.ty(&mut store).clone(), function_type);
let function_type = FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); let function_type = FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]);
let function = Function::new( let function = Function::new(
&mut store, &mut store,
&function_type, &function_type,
|_values: &[Value]| unimplemented!(), |_values: &[Value]| unimplemented!(),
); );
assert_eq!(function.ty(&mut store), function_type); assert_eq!(function.ty(&mut store).clone(), function_type);
let function_type = FunctionType::new(vec![], vec![Type::I32]); let function_type = FunctionType::new(vec![], vec![Type::I32]);
let function = Function::new( let function = Function::new(
&mut store, &mut store,
&function_type, &function_type,
|_values: &[Value]| unimplemented!(), |_values: &[Value]| unimplemented!(),
); );
assert_eq!(function.ty(&mut store), function_type); assert_eq!(function.ty(&mut store).clone(), function_type);
let function_type = FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); let function_type = FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]);
let function = Function::new( let function = Function::new(
&mut store, &mut store,
&function_type, &function_type,
|_values: &[Value]| unimplemented!(), |_values: &[Value]| unimplemented!(),
); );
assert_eq!(function.ty(&mut store), function_type); assert_eq!(function.ty(&mut store).clone(), function_type);
// Using array signature // Using array signature
let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]);
@@ -350,7 +356,7 @@ fn function_new_dynamic_env() -> Result<(), String> {
&function_type, &function_type,
|_env: FunctionEnvMut<MyEnv>, _values: &[Value]| unimplemented!(), |_env: FunctionEnvMut<MyEnv>, _values: &[Value]| unimplemented!(),
); );
assert_eq!(function.ty(&mut store), function_type); assert_eq!(function.ty(&mut store).clone(), function_type);
let function_type = FunctionType::new(vec![Type::I32], vec![]); let function_type = FunctionType::new(vec![Type::I32], vec![]);
let function = Function::new_with_env( let function = Function::new_with_env(
&mut store, &mut store,
@@ -358,7 +364,7 @@ fn function_new_dynamic_env() -> Result<(), String> {
&function_type, &function_type,
|_env: FunctionEnvMut<MyEnv>, _values: &[Value]| unimplemented!(), |_env: FunctionEnvMut<MyEnv>, _values: &[Value]| unimplemented!(),
); );
assert_eq!(function.ty(&mut store), function_type); assert_eq!(function.ty(&mut store).clone(), function_type);
let function_type = FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); let function_type = FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]);
let function = Function::new_with_env( let function = Function::new_with_env(
&mut store, &mut store,
@@ -366,7 +372,7 @@ fn function_new_dynamic_env() -> Result<(), String> {
&function_type, &function_type,
|_env: FunctionEnvMut<MyEnv>, _values: &[Value]| unimplemented!(), |_env: FunctionEnvMut<MyEnv>, _values: &[Value]| unimplemented!(),
); );
assert_eq!(function.ty(&mut store), function_type); assert_eq!(function.ty(&mut store).clone(), function_type);
let function_type = FunctionType::new(vec![], vec![Type::I32]); let function_type = FunctionType::new(vec![], vec![Type::I32]);
let function = Function::new_with_env( let function = Function::new_with_env(
&mut store, &mut store,
@@ -374,7 +380,7 @@ fn function_new_dynamic_env() -> Result<(), String> {
&function_type, &function_type,
|_env: FunctionEnvMut<MyEnv>, _values: &[Value]| unimplemented!(), |_env: FunctionEnvMut<MyEnv>, _values: &[Value]| unimplemented!(),
); );
assert_eq!(function.ty(&mut store), function_type); assert_eq!(function.ty(&mut store).clone(), function_type);
let function_type = FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); let function_type = FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]);
let function = Function::new_with_env( let function = Function::new_with_env(
&mut store, &mut store,
@@ -382,7 +388,7 @@ fn function_new_dynamic_env() -> Result<(), String> {
&function_type, &function_type,
|_env: FunctionEnvMut<MyEnv>, _values: &[Value]| unimplemented!(), |_env: FunctionEnvMut<MyEnv>, _values: &[Value]| unimplemented!(),
); );
assert_eq!(function.ty(&mut store), function_type); assert_eq!(function.ty(&mut store).clone(), function_type);
// Using array signature // Using array signature
let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]);

View File

@@ -367,7 +367,7 @@ pub mod reference_types {
let global: &Global = instance.exports.get_global("global")?; let global: &Global = instance.exports.get_global("global")?;
{ {
let er = ExternRef::new(&mut store, 3usize); let er = ExternRef::new(&mut store, 3usize);
global.set(&mut store, Value::ExternRef(Some(er)))?; global.set(&mut store, Value::ExternRef(Some(er.clone())))?;
} }
let get_from_global: TypedFunction<(), Option<ExternRef>> = instance let get_from_global: TypedFunction<(), Option<ExternRef>> = instance
.exports .exports
@@ -398,7 +398,7 @@ pub mod reference_types {
let er = ExternRef::new(&mut store, 3usize); let er = ExternRef::new(&mut store, 3usize);
let result = pass_extern_ref.call(&mut store, Some(er)); let result = pass_extern_ref.call(&mut store, Some(er.clone()));
assert!(result.is_err()); assert!(result.is_err());
Ok(()) Ok(())
@@ -442,7 +442,7 @@ pub mod reference_types {
let result = grow_table_with_ref.call(&mut store, Some(er1.clone()), 10_000)?; let result = grow_table_with_ref.call(&mut store, Some(er1.clone()), 10_000)?;
assert_eq!(result, -1); assert_eq!(result, -1);
let result = grow_table_with_ref.call(&mut store, Some(er1), 8)?; let result = grow_table_with_ref.call(&mut store, Some(er1.clone()), 8)?;
assert_eq!(result, 2); assert_eq!(result, 2);
for i in 2..10 { for i in 2..10 {
@@ -454,7 +454,7 @@ pub mod reference_types {
} }
{ {
fill_table_with_ref.call(&mut store, Some(er2), 0, 2)?; fill_table_with_ref.call(&mut store, Some(er2.clone()), 0, 2)?;
} }
{ {
@@ -462,7 +462,7 @@ pub mod reference_types {
table2.set(&mut store, 1, Value::ExternRef(Some(er3.clone())))?; table2.set(&mut store, 1, Value::ExternRef(Some(er3.clone())))?;
table2.set(&mut store, 2, Value::ExternRef(Some(er3.clone())))?; table2.set(&mut store, 2, Value::ExternRef(Some(er3.clone())))?;
table2.set(&mut store, 3, Value::ExternRef(Some(er3.clone())))?; table2.set(&mut store, 3, Value::ExternRef(Some(er3.clone())))?;
table2.set(&mut store, 4, Value::ExternRef(Some(er3)))?; table2.set(&mut store, 4, Value::ExternRef(Some(er3.clone())))?;
} }
{ {

File diff suppressed because it is too large Load Diff

View File

@@ -357,7 +357,7 @@ impl VMMemory {
/// ///
/// This creates a `Memory` with owned metadata: this can be used to create a memory /// This creates a `Memory` with owned metadata: this can be used to create a memory
/// that will be imported into Wasm modules. /// that will be imported into Wasm modules.
pub fn new(memory: &MemoryType, style: &MemoryStyle) -> Result<Self, MemoryError> { pub fn new(memory: &MemoryType, style: &MemoryStyle) -> Result<VMMemory, MemoryError> {
Ok(Self(Box::new(VMOwnedMemory::new(memory, style)?))) Ok(Self(Box::new(VMOwnedMemory::new(memory, style)?)))
} }
@@ -377,7 +377,7 @@ impl VMMemory {
memory: &MemoryType, memory: &MemoryType,
style: &MemoryStyle, style: &MemoryStyle,
vm_memory_location: NonNull<VMMemoryDefinition>, vm_memory_location: NonNull<VMMemoryDefinition>,
) -> Result<Self, MemoryError> { ) -> Result<VMMemory, MemoryError> {
Ok(Self(Box::new(VMOwnedMemory::from_definition( Ok(Self(Box::new(VMOwnedMemory::from_definition(
memory, memory,
style, style,
@@ -389,9 +389,9 @@ impl VMMemory {
/// are natively supported /// are natively supported
/// - VMOwnedMemory -> VMMemory /// - VMOwnedMemory -> VMMemory
/// - Box<dyn LinearMemory + 'static> -> VMMemory /// - Box<dyn LinearMemory + 'static> -> VMMemory
pub fn from_custom<IntoVMMemory>(memory: IntoVMMemory) -> Self pub fn from_custom<IntoVMMemory>(memory: IntoVMMemory) -> VMMemory
where where
IntoVMMemory: Into<Self>, IntoVMMemory: Into<VMMemory>,
{ {
memory.into() memory.into()
} }

View File

@@ -47,9 +47,8 @@ pub mod runners;
use crate::syscalls::*; use crate::syscalls::*;
pub use crate::state::{ pub use crate::state::{
Fd, Pipe, Stderr, Stdin, Stdout, WasiBidirectionalPipePair, WasiBidirectionalSharedPipePair, Fd, Pipe, Stderr, Stdin, Stdout, WasiFs, WasiInodes, WasiState, WasiStateBuilder,
WasiFs, WasiInodes, WasiPipe, WasiState, WasiStateBuilder, WasiStateCreationError, ALL_RIGHTS, WasiStateCreationError, ALL_RIGHTS, VIRTUAL_ROOT_FD,
VIRTUAL_ROOT_FD,
}; };
pub use crate::syscalls::types; pub use crate::syscalls::types;
#[cfg(feature = "wasix")] #[cfg(feature = "wasix")]

View File

@@ -2,14 +2,12 @@ use crate::syscalls::types::*;
use crate::syscalls::{read_bytes, write_bytes}; use crate::syscalls::{read_bytes, write_bytes};
use bytes::{Buf, Bytes}; use bytes::{Buf, Bytes};
use std::convert::TryInto; use std::convert::TryInto;
use std::io::{self, Read, Seek, SeekFrom, Write}; use std::io::{self, Read};
use std::ops::DerefMut; use std::ops::DerefMut;
use std::sync::mpsc; use std::sync::mpsc;
use std::sync::Arc;
use std::sync::Mutex; use std::sync::Mutex;
use wasmer::WasmSlice; use wasmer::WasmSlice;
use wasmer::{MemorySize, MemoryView}; use wasmer::{MemorySize, MemoryView};
use wasmer_vfs::{FsError, VirtualFile};
use wasmer_wasi_types::wasi::Errno; use wasmer_wasi_types::wasi::Errno;
#[derive(Debug)] #[derive(Debug)]
@@ -20,70 +18,10 @@ pub struct WasiPipe {
rx: Mutex<mpsc::Receiver<Vec<u8>>>, rx: Mutex<mpsc::Receiver<Vec<u8>>>,
/// Buffers the last read message from the pipe while its being consumed /// Buffers the last read message from the pipe while its being consumed
read_buffer: Option<Bytes>, read_buffer: Option<Bytes>,
/// Whether the pipe should block or not block to wait for stdin reads
block: bool,
} }
/// Pipe pair of (a, b) WasiPipes that are connected together impl WasiPipe {
#[derive(Debug)] pub fn new() -> (WasiPipe, WasiPipe) {
pub struct WasiBidirectionalPipePair {
pub send: WasiPipe,
pub recv: WasiPipe,
}
impl Write for WasiBidirectionalPipePair {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.send.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.send.flush()
}
}
impl Seek for WasiBidirectionalPipePair {
fn seek(&mut self, _: SeekFrom) -> io::Result<u64> {
Ok(0)
}
}
impl Read for WasiBidirectionalPipePair {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
self.recv.read(buf)
}
}
impl VirtualFile for WasiBidirectionalPipePair {
fn last_accessed(&self) -> u64 {
self.recv.last_accessed()
}
fn last_modified(&self) -> u64 {
self.recv.last_modified()
}
fn created_time(&self) -> u64 {
self.recv.created_time()
}
fn size(&self) -> u64 {
self.recv.size()
}
fn set_len(&mut self, i: u64) -> Result<(), FsError> {
self.recv.set_len(i)
}
fn unlink(&mut self) -> Result<(), FsError> {
self.recv.unlink()
}
fn bytes_available_read(&self) -> Result<Option<usize>, FsError> {
self.recv.bytes_available_read()
}
}
impl Default for WasiBidirectionalPipePair {
fn default() -> Self {
Self::new()
}
}
impl WasiBidirectionalPipePair {
pub fn new() -> WasiBidirectionalPipePair {
let (tx1, rx1) = mpsc::channel(); let (tx1, rx1) = mpsc::channel();
let (tx2, rx2) = mpsc::channel(); let (tx2, rx2) = mpsc::channel();
@@ -91,142 +29,15 @@ impl WasiBidirectionalPipePair {
tx: Mutex::new(tx1), tx: Mutex::new(tx1),
rx: Mutex::new(rx2), rx: Mutex::new(rx2),
read_buffer: None, read_buffer: None,
block: true,
}; };
let pipe2 = WasiPipe { let pipe2 = WasiPipe {
tx: Mutex::new(tx2), tx: Mutex::new(tx2),
rx: Mutex::new(rx1), rx: Mutex::new(rx1),
read_buffer: None, read_buffer: None,
block: true,
}; };
WasiBidirectionalPipePair { (pipe1, pipe2)
send: pipe1,
recv: pipe2,
}
}
#[allow(dead_code)]
pub fn with_blocking(mut self, block: bool) -> Self {
self.set_blocking(block);
self
}
/// Whether to block on reads (ususally for waiting for stdin keyboard input). Default: `true`
#[allow(dead_code)]
pub fn set_blocking(&mut self, block: bool) {
self.send.set_blocking(block);
self.recv.set_blocking(block);
}
}
/// Shared version of WasiBidirectionalPipePair for situations where you need
/// to emulate the old behaviour of `Pipe` (both send and recv on one channel).
#[derive(Debug, Clone)]
pub struct WasiBidirectionalSharedPipePair {
inner: Arc<Mutex<WasiBidirectionalPipePair>>,
}
impl Default for WasiBidirectionalSharedPipePair {
fn default() -> Self {
Self::new()
}
}
impl WasiBidirectionalSharedPipePair {
pub fn new() -> Self {
Self {
inner: Arc::new(Mutex::new(WasiBidirectionalPipePair::new())),
}
}
#[allow(dead_code)]
pub fn with_blocking(mut self, block: bool) -> Self {
self.set_blocking(block);
self
}
/// Whether to block on reads (ususally for waiting for stdin keyboard input). Default: `true`
#[allow(dead_code)]
pub fn set_blocking(&mut self, block: bool) {
self.inner.lock().unwrap().set_blocking(block);
}
}
impl Write for WasiBidirectionalSharedPipePair {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
match self.inner.lock().as_mut().map(|l| l.write(buf)) {
Ok(r) => r,
Err(_) => Ok(0),
}
}
fn flush(&mut self) -> io::Result<()> {
match self.inner.lock().as_mut().map(|l| l.flush()) {
Ok(r) => r,
Err(_) => Ok(()),
}
}
}
impl Seek for WasiBidirectionalSharedPipePair {
fn seek(&mut self, _: SeekFrom) -> io::Result<u64> {
Ok(0)
}
}
impl Read for WasiBidirectionalSharedPipePair {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
match self.inner.lock().as_mut().map(|l| l.read(buf)) {
Ok(r) => r,
Err(_) => Ok(0),
}
}
}
impl VirtualFile for WasiBidirectionalSharedPipePair {
fn last_accessed(&self) -> u64 {
self.inner.lock().map(|l| l.last_accessed()).unwrap_or(0)
}
fn last_modified(&self) -> u64 {
self.inner.lock().map(|l| l.last_modified()).unwrap_or(0)
}
fn created_time(&self) -> u64 {
self.inner.lock().map(|l| l.created_time()).unwrap_or(0)
}
fn size(&self) -> u64 {
self.inner.lock().map(|l| l.size()).unwrap_or(0)
}
fn set_len(&mut self, i: u64) -> Result<(), FsError> {
match self.inner.lock().as_mut().map(|l| l.set_len(i)) {
Ok(r) => r,
Err(_) => Err(FsError::Lock),
}
}
fn unlink(&mut self) -> Result<(), FsError> {
match self.inner.lock().as_mut().map(|l| l.unlink()) {
Ok(r) => r,
Err(_) => Err(FsError::Lock),
}
}
fn bytes_available_read(&self) -> Result<Option<usize>, FsError> {
self.inner
.lock()
.map(|l| l.bytes_available_read())
.unwrap_or(Ok(None))
}
}
impl WasiPipe {
/// Same as `set_blocking`, but as a builder method
pub fn with_blocking(mut self, block: bool) -> Self {
self.set_blocking(block);
self
}
/// Whether to block on reads (ususally for waiting for stdin keyboard input). Default: `true`
pub fn set_blocking(&mut self, block: bool) {
self.block = block;
} }
pub fn recv<M: MemorySize>( pub fn recv<M: MemorySize>(
@@ -283,113 +94,26 @@ impl WasiPipe {
} }
} }
impl Write for WasiPipe {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let buf_len = buf.len();
let tx = self.tx.lock().unwrap();
tx.send(buf.to_vec())
.map_err(|e| io::Error::new(io::ErrorKind::Other, format!("{e}")))?;
Ok(buf_len)
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl Seek for WasiPipe {
fn seek(&mut self, _: SeekFrom) -> io::Result<u64> {
Ok(0)
}
}
impl Read for WasiPipe { impl Read for WasiPipe {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> { fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
loop { loop {
if let Some(inner_buf) = self.read_buffer.as_mut() { if let Some(inner_buf) = self.read_buffer.as_mut() {
let buf_len = inner_buf.len(); let buf_len = inner_buf.len();
if buf_len > 0 { if buf_len > 0 {
if inner_buf.len() > buf.len() {
let mut reader = inner_buf.as_ref();
let read = reader.read_exact(buf).map(|_| buf.len())?;
inner_buf.advance(read);
return Ok(read);
} else {
let mut reader = inner_buf.as_ref(); let mut reader = inner_buf.as_ref();
let read = reader.read(buf).map(|_| buf_len as usize)?; let read = reader.read(buf).map(|_| buf_len as usize)?;
inner_buf.advance(read); inner_buf.advance(read);
return Ok(read); return Ok(read);
} }
} }
}
let rx = self.rx.lock().unwrap(); let rx = self.rx.lock().unwrap();
let data = rx.recv().map_err(|_| {
// We need to figure out whether we need to block here. io::Error::new(
// The problem is that in cases of multiple buffered reads like: io::ErrorKind::BrokenPipe,
// "the wasi pipe is not connected".to_string(),
// println!("abc"); )
// println!("def"); })?;
//
// get_stdout() // would only return "abc\n" instead of "abc\ndef\n"
let data = match rx.try_recv() {
Ok(mut s) => {
s.append(&mut rx.try_iter().flat_map(|f| f.into_iter()).collect());
s
}
Err(_) => {
if !self.block {
// If self.block is explicitly set to false, never block
Vec::new()
} else {
// could not immediately receive bytes, so we need to block
match rx.recv() {
Ok(o) => o,
// Errors can happen if the sender has been dropped already
// In this case, just return 0 to indicate that we can't read any
// bytes anymore
Err(_) => {
return Ok(0);
}
}
}
}
};
if data.is_empty() && self.read_buffer.as_ref().map(|s| s.len()).unwrap_or(0) == 0 {
return Ok(0);
}
self.read_buffer.replace(Bytes::from(data)); self.read_buffer.replace(Bytes::from(data));
} }
} }
} }
impl VirtualFile for WasiPipe {
fn last_accessed(&self) -> u64 {
0
}
fn last_modified(&self) -> u64 {
0
}
fn created_time(&self) -> u64 {
0
}
fn size(&self) -> u64 {
self.read_buffer
.as_ref()
.map(|s| s.len() as u64)
.unwrap_or_default()
}
fn set_len(&mut self, _: u64) -> Result<(), FsError> {
Ok(())
}
fn unlink(&mut self) -> Result<(), FsError> {
Ok(())
}
fn bytes_available_read(&self) -> Result<Option<usize>, FsError> {
Ok(Some(
self.read_buffer
.as_ref()
.map(|s| s.len())
.unwrap_or_default(),
))
}
}

View File

@@ -3,7 +3,12 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[cfg(all(unix, feature = "sys-poll"))] #[cfg(all(unix, feature = "sys-poll"))]
use std::convert::TryInto; use std::convert::TryInto;
use std::time::Duration; use std::{
collections::VecDeque,
io::{self, Read, Seek, Write},
sync::{Arc, Mutex},
time::Duration,
};
use wasmer_vbus::BusError; use wasmer_vbus::BusError;
use wasmer_wasi_types::wasi::{BusErrno, Errno}; use wasmer_wasi_types::wasi::{BusErrno, Errno};
@@ -371,11 +376,79 @@ pub(crate) fn poll(
pub trait WasiPath {} pub trait WasiPath {}
#[deprecated( /// For piping stdio. Stores all output / input in a byte-vector.
since = "3.0.0-beta.2", #[derive(Debug, Clone, Default)]
note = "Moved to `wasmer_wasi::pipe::WasiBidirectionalSharedPipePair`, `Pipe` is only a transitional reexport" #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
)] pub struct Pipe {
pub use crate::state::WasiBidirectionalSharedPipePair as Pipe; buffer: Arc<Mutex<VecDeque<u8>>>,
}
impl Pipe {
pub fn new() -> Self {
Self::default()
}
}
impl Read for Pipe {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let mut buffer = self.buffer.lock().unwrap();
let amt = std::cmp::min(buf.len(), buffer.len());
let buf_iter = buffer.drain(..amt).enumerate();
for (i, byte) in buf_iter {
buf[i] = byte;
}
Ok(amt)
}
}
impl Write for Pipe {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let mut buffer = self.buffer.lock().unwrap();
buffer.extend(buf);
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl Seek for Pipe {
fn seek(&mut self, _pos: io::SeekFrom) -> io::Result<u64> {
Err(io::Error::new(
io::ErrorKind::Other,
"can not seek in a pipe",
))
}
}
//#[cfg_attr(feature = "enable-serde", typetag::serde)]
impl VirtualFile for Pipe {
fn last_accessed(&self) -> u64 {
0
}
fn last_modified(&self) -> u64 {
0
}
fn created_time(&self) -> u64 {
0
}
fn size(&self) -> u64 {
let buffer = self.buffer.lock().unwrap();
buffer.len() as u64
}
fn set_len(&mut self, len: u64) -> Result<(), FsError> {
let mut buffer = self.buffer.lock().unwrap();
buffer.resize(len as usize, 0);
Ok(())
}
fn unlink(&mut self) -> Result<(), FsError> {
Ok(())
}
fn bytes_available_read(&self) -> Result<Option<usize>, FsError> {
let buffer = self.buffer.lock().unwrap();
Ok(Some(buffer.len()))
}
}
/* /*
TODO: Think about using this TODO: Think about using this

View File

@@ -43,7 +43,7 @@ use crate::{
state::{ state::{
self, fs_error_into_wasi_err, iterate_poll_events, net_error_into_wasi_err, poll, self, fs_error_into_wasi_err, iterate_poll_events, net_error_into_wasi_err, poll,
virtual_file_type_to_wasi_file_type, Inode, InodeSocket, InodeSocketKind, InodeVal, Kind, virtual_file_type_to_wasi_file_type, Inode, InodeSocket, InodeSocketKind, InodeVal, Kind,
PollEvent, PollEventBuilder, WasiBidirectionalPipePair, WasiState, MAX_SYMLINKS, PollEvent, PollEventBuilder, WasiPipe, WasiState, MAX_SYMLINKS,
}, },
Fd, WasiEnv, WasiError, WasiThread, WasiThreadId, Fd, WasiEnv, WasiError, WasiThread, WasiThreadId,
}; };
@@ -1804,9 +1804,7 @@ pub fn fd_pipe<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, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0);
let pipes = WasiBidirectionalPipePair::new(); let (pipe1, pipe2) = WasiPipe::new();
let pipe1 = pipes.send;
let pipe2 = pipes.recv;
let inode1 = state.fs.create_inode_with_default_stat( let inode1 = state.fs.create_inode_with_default_stat(
inodes.deref_mut(), inodes.deref_mut(),

View File

@@ -1,7 +1,7 @@
use std::io::{Read, Write}; use std::io::{Read, Write};
use wasmer::{Instance, Module, Store}; use wasmer::{Instance, Module, Store};
use wasmer_wasi::{WasiBidirectionalSharedPipePair, WasiState}; use wasmer_wasi::{Pipe, WasiState};
mod sys { mod sys {
#[test] #[test]
@@ -73,10 +73,10 @@ fn test_stdout() {
"#).unwrap(); "#).unwrap();
// Create the `WasiEnv`. // Create the `WasiEnv`.
let mut pipe = WasiBidirectionalSharedPipePair::new().with_blocking(false); let mut stdout = Pipe::default();
let wasi_env = WasiState::new("command-name") let wasi_env = WasiState::new("command-name")
.args(&["Gordon"]) .args(&["Gordon"])
.stdout(Box::new(pipe.clone())) .stdout(Box::new(stdout.clone()))
.finalize(&mut store) .finalize(&mut store)
.unwrap(); .unwrap();
@@ -93,7 +93,7 @@ fn test_stdout() {
start.call(&mut store, &[]).unwrap(); start.call(&mut store, &[]).unwrap();
let mut stdout_str = String::new(); let mut stdout_str = String::new();
pipe.read_to_string(&mut stdout_str).unwrap(); stdout.read_to_string(&mut stdout_str).unwrap();
let stdout_as_str = stdout_str.as_str(); let stdout_as_str = stdout_str.as_str();
assert_eq!(stdout_as_str, "hello world\n"); assert_eq!(stdout_as_str, "hello world\n");
} }
@@ -110,7 +110,7 @@ fn test_env() {
}); });
// Create the `WasiEnv`. // Create the `WasiEnv`.
let mut pipe = WasiBidirectionalSharedPipePair::new().with_blocking(false); let mut stdout = Pipe::new();
let mut wasi_state_builder = WasiState::new("command-name"); let mut wasi_state_builder = WasiState::new("command-name");
wasi_state_builder wasi_state_builder
.args(&["Gordon"]) .args(&["Gordon"])
@@ -119,7 +119,7 @@ fn test_env() {
.env("TEST2", "VALUE2"); .env("TEST2", "VALUE2");
// panic!("envs: {:?}", wasi_state_builder.envs); // panic!("envs: {:?}", wasi_state_builder.envs);
let wasi_env = wasi_state_builder let wasi_env = wasi_state_builder
.stdout(Box::new(pipe.clone())) .stdout(Box::new(stdout.clone()))
.finalize(&mut store) .finalize(&mut store)
.unwrap(); .unwrap();
@@ -136,7 +136,7 @@ fn test_env() {
start.call(&mut store, &[]).unwrap(); start.call(&mut store, &[]).unwrap();
let mut stdout_str = String::new(); let mut stdout_str = String::new();
pipe.read_to_string(&mut stdout_str).unwrap(); stdout.read_to_string(&mut stdout_str).unwrap();
let stdout_as_str = stdout_str.as_str(); let stdout_as_str = stdout_str.as_str();
assert_eq!(stdout_as_str, "Env vars:\nDOG=X\nTEST2=VALUE2\nTEST=VALUE\nDOG Ok(\"X\")\nDOG_TYPE Err(NotPresent)\nSET VAR Ok(\"HELLO\")\n"); assert_eq!(stdout_as_str, "Env vars:\nDOG=X\nTEST2=VALUE2\nTEST=VALUE\nDOG Ok(\"X\")\nDOG_TYPE Err(NotPresent)\nSET VAR Ok(\"HELLO\")\n");
} }
@@ -146,16 +146,15 @@ fn test_stdin() {
let module = Module::new(&store, include_bytes!("stdin-hello.wasm")).unwrap(); let module = Module::new(&store, include_bytes!("stdin-hello.wasm")).unwrap();
// Create the `WasiEnv`. // Create the `WasiEnv`.
let mut pipe = WasiBidirectionalSharedPipePair::new().with_blocking(false); let mut stdin = Pipe::new();
let wasi_env = WasiState::new("command-name")
.stdin(Box::new(stdin.clone()))
.finalize(&mut store)
.unwrap();
// Write to STDIN // Write to STDIN
let buf = "Hello, stdin!\n".as_bytes().to_owned(); let buf = "Hello, stdin!\n".as_bytes().to_owned();
pipe.write(&buf[..]).unwrap(); stdin.write(&buf[..]).unwrap();
let wasi_env = WasiState::new("command-name")
.stdin(Box::new(pipe.clone()))
.finalize(&mut store)
.unwrap();
// Generate an `ImportObject`. // Generate an `ImportObject`.
let import_object = wasi_env.import_object(&mut store, &module).unwrap(); let import_object = wasi_env.import_object(&mut store, &module).unwrap();
@@ -168,10 +167,10 @@ fn test_stdin() {
// Let's call the `_start` function, which is our `main` function in Rust. // Let's call the `_start` function, which is our `main` function in Rust.
let start = instance.exports.get_function("_start").unwrap(); let start = instance.exports.get_function("_start").unwrap();
let result = start.call(&mut store, &[]); let result = start.call(&mut store, &[]);
assert!(result.is_ok()); assert!(!result.is_err());
// We assure stdin is now empty // We assure stdin is now empty
let mut buf = Vec::new(); let mut buf = Vec::new();
pipe.read_to_end(&mut buf).unwrap(); stdin.read_to_end(&mut buf).unwrap();
assert_eq!(buf.len(), 0); assert_eq!(buf.len(), 0);
} }

View File

@@ -277,7 +277,7 @@ fn create_obj(args: Vec<&'static str>, keyword_needle: &str, keyword: &str) -> a
let object_path = operating_dir.join("wasm.obj"); let object_path = operating_dir.join("wasm.obj");
let output: Vec<u8> = WasmerCreateObj { let output: Vec<u8> = WasmerCreateObj {
current_dir: operating_dir, current_dir: operating_dir.clone(),
wasm_path, wasm_path,
output_object_path: object_path.clone(), output_object_path: object_path.clone(),
compiler: Compiler::Cranelift, compiler: Compiler::Cranelift,
@@ -292,7 +292,7 @@ fn create_obj(args: Vec<&'static str>, keyword_needle: &str, keyword: &str) -> a
"create-obj successfully completed but object output file `{}` missing", "create-obj successfully completed but object output file `{}` missing",
object_path.display() object_path.display()
); );
let mut object_header_path = object_path; let mut object_header_path = object_path.clone();
object_header_path.set_extension("h"); object_header_path.set_extension("h");
assert!( assert!(
object_header_path.exists(), object_header_path.exists(),

View File

@@ -40,8 +40,9 @@ mod tests {
*/ */
let command_success = command.status.success(); let command_success = command.status.success();
let test_success = !stderr.contains("** TEST FAILED **"); let test_success = !stderr.contains("** TEST FAILED **");
let success = command_success && test_success;
command_success && test_success success
} }
fn remove_existing_artificats() -> Output { fn remove_existing_artificats() -> Output {

View File

@@ -7,8 +7,8 @@ use wasmer::{FunctionEnv, Imports, Instance, Module, Store};
use wasmer_vfs::{host_fs, mem_fs, FileSystem}; use wasmer_vfs::{host_fs, mem_fs, FileSystem};
use wasmer_wasi::types::wasi::{Filesize, Timestamp}; use wasmer_wasi::types::wasi::{Filesize, Timestamp};
use wasmer_wasi::{ use wasmer_wasi::{
generate_import_object_from_env, get_wasi_version, FsError, VirtualFile, generate_import_object_from_env, get_wasi_version, FsError, Pipe, VirtualFile, WasiEnv,
WasiBidirectionalPipePair, WasiEnv, WasiFunctionEnv, WasiState, WasiVersion, WasiFunctionEnv, WasiState, WasiVersion,
}; };
use wast::parser::{self, Parse, ParseBuffer, Parser}; use wast::parser::{self, Parse, ParseBuffer, Parser};
@@ -142,7 +142,7 @@ impl<'a> WasiTest<'a> {
)> { )> {
let mut builder = WasiState::new(self.wasm_path); let mut builder = WasiState::new(self.wasm_path);
let stdin_pipe = WasiBidirectionalPipePair::new().with_blocking(false); let stdin_pipe = Pipe::new();
builder.stdin(Box::new(stdin_pipe)); builder.stdin(Box::new(stdin_pipe));
for (name, value) in &self.envs { for (name, value) in &self.envs {