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]]
name = "wasmer-inline-c"
version = "0.1.2"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c4e7a2a3363ceeb2ee60371af9460748f2bf53569b58627f1f640284ab07778"
checksum = "e2405c99de49dc05338e5ed2eb397fe70b7128340d960507d0ba716f7d29a91a"
dependencies = [
"assert_cmd",
"cc",

View File

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

View File

@@ -210,25 +210,28 @@ fn memory_grow() -> Result<(), String> {
fn function_new() -> Result<(), String> {
let mut store = Store::default();
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| {});
assert_eq!(
function.ty(&mut store),
function.ty(&mut store).clone(),
FunctionType::new(vec![Type::I32], vec![])
);
let function = Function::new_typed(&mut store, |_a: i32, _b: i64, _c: f32, _d: f64| {});
assert_eq!(
function.ty(&mut store),
function.ty(&mut store).clone(),
FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![])
);
let function = Function::new_typed(&mut store, || -> i32 { 1 });
assert_eq!(
function.ty(&mut store),
function.ty(&mut store).clone(),
FunctionType::new(vec![], vec![Type::I32])
);
let function = Function::new_typed(&mut store, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) });
assert_eq!(
function.ty(&mut store),
function.ty(&mut store).clone(),
FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64])
);
Ok(())
@@ -243,11 +246,14 @@ fn function_new_env() -> Result<(), String> {
let my_env = MyEnv {};
let env = FunctionEnv::new(&mut store, my_env);
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 =
Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut<MyEnv>, _a: i32| {});
assert_eq!(
function.ty(&mut store),
function.ty(&mut store).clone(),
FunctionType::new(vec![Type::I32], vec![])
);
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| {},
);
assert_eq!(
function.ty(&mut store),
function.ty(&mut store).clone(),
FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![])
);
let function =
Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut<MyEnv>| -> i32 { 1 });
assert_eq!(
function.ty(&mut store),
function.ty(&mut store).clone(),
FunctionType::new(vec![], vec![Type::I32])
);
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) },
);
assert_eq!(
function.ty(&mut store),
function.ty(&mut store).clone(),
FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64])
);
Ok(())
@@ -288,35 +294,35 @@ fn function_new_dynamic() -> Result<(), String> {
&function_type,
|_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 = Function::new(
&mut store,
&function_type,
|_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 = Function::new(
&mut store,
&function_type,
|_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 = Function::new(
&mut store,
&function_type,
|_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 = Function::new(
&mut store,
&function_type,
|_values: &[Value]| unimplemented!(),
);
assert_eq!(function.ty(&mut store), function_type);
assert_eq!(function.ty(&mut store).clone(), function_type);
// Using array signature
let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]);
@@ -350,7 +356,7 @@ fn function_new_dynamic_env() -> Result<(), String> {
&function_type,
|_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 = Function::new_with_env(
&mut store,
@@ -358,7 +364,7 @@ fn function_new_dynamic_env() -> Result<(), String> {
&function_type,
|_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 = Function::new_with_env(
&mut store,
@@ -366,7 +372,7 @@ fn function_new_dynamic_env() -> Result<(), String> {
&function_type,
|_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 = Function::new_with_env(
&mut store,
@@ -374,7 +380,7 @@ fn function_new_dynamic_env() -> Result<(), String> {
&function_type,
|_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 = Function::new_with_env(
&mut store,
@@ -382,7 +388,7 @@ fn function_new_dynamic_env() -> Result<(), String> {
&function_type,
|_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
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 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
.exports
@@ -398,7 +398,7 @@ pub mod reference_types {
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());
Ok(())
@@ -442,7 +442,7 @@ pub mod reference_types {
let result = grow_table_with_ref.call(&mut store, Some(er1.clone()), 10_000)?;
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);
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, 2, 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
/// 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)?)))
}
@@ -377,7 +377,7 @@ impl VMMemory {
memory: &MemoryType,
style: &MemoryStyle,
vm_memory_location: NonNull<VMMemoryDefinition>,
) -> Result<Self, MemoryError> {
) -> Result<VMMemory, MemoryError> {
Ok(Self(Box::new(VMOwnedMemory::from_definition(
memory,
style,
@@ -389,9 +389,9 @@ impl VMMemory {
/// are natively supported
/// - VMOwnedMemory -> VMMemory
/// - Box<dyn LinearMemory + 'static> -> VMMemory
pub fn from_custom<IntoVMMemory>(memory: IntoVMMemory) -> Self
pub fn from_custom<IntoVMMemory>(memory: IntoVMMemory) -> VMMemory
where
IntoVMMemory: Into<Self>,
IntoVMMemory: Into<VMMemory>,
{
memory.into()
}

View File

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

View File

@@ -2,14 +2,12 @@ use crate::syscalls::types::*;
use crate::syscalls::{read_bytes, write_bytes};
use bytes::{Buf, Bytes};
use std::convert::TryInto;
use std::io::{self, Read, Seek, SeekFrom, Write};
use std::io::{self, Read};
use std::ops::DerefMut;
use std::sync::mpsc;
use std::sync::Arc;
use std::sync::Mutex;
use wasmer::WasmSlice;
use wasmer::{MemorySize, MemoryView};
use wasmer_vfs::{FsError, VirtualFile};
use wasmer_wasi_types::wasi::Errno;
#[derive(Debug)]
@@ -20,70 +18,10 @@ pub struct WasiPipe {
rx: Mutex<mpsc::Receiver<Vec<u8>>>,
/// Buffers the last read message from the pipe while its being consumed
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
#[derive(Debug)]
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 {
impl WasiPipe {
pub fn new() -> (WasiPipe, WasiPipe) {
let (tx1, rx1) = mpsc::channel();
let (tx2, rx2) = mpsc::channel();
@@ -91,142 +29,15 @@ impl WasiBidirectionalPipePair {
tx: Mutex::new(tx1),
rx: Mutex::new(rx2),
read_buffer: None,
block: true,
};
let pipe2 = WasiPipe {
tx: Mutex::new(tx2),
rx: Mutex::new(rx1),
read_buffer: None,
block: true,
};
WasiBidirectionalPipePair {
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;
(pipe1, pipe2)
}
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 {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
loop {
if let Some(inner_buf) = self.read_buffer.as_mut() {
let buf_len = inner_buf.len();
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 read = reader.read(buf).map(|_| buf_len as usize)?;
inner_buf.advance(read);
return Ok(read);
}
}
}
let rx = self.rx.lock().unwrap();
// We need to figure out whether we need to block here.
// The problem is that in cases of multiple buffered reads like:
//
// 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);
}
let data = rx.recv().map_err(|_| {
io::Error::new(
io::ErrorKind::BrokenPipe,
"the wasi pipe is not connected".to_string(),
)
})?;
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};
#[cfg(all(unix, feature = "sys-poll"))]
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_wasi_types::wasi::{BusErrno, Errno};
@@ -371,11 +376,79 @@ pub(crate) fn poll(
pub trait WasiPath {}
#[deprecated(
since = "3.0.0-beta.2",
note = "Moved to `wasmer_wasi::pipe::WasiBidirectionalSharedPipePair`, `Pipe` is only a transitional reexport"
)]
pub use crate::state::WasiBidirectionalSharedPipePair as Pipe;
/// For piping stdio. Stores all output / input in a byte-vector.
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct 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

View File

@@ -43,7 +43,7 @@ use crate::{
state::{
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,
PollEvent, PollEventBuilder, WasiBidirectionalPipePair, WasiState, MAX_SYMLINKS,
PollEvent, PollEventBuilder, WasiPipe, WasiState, MAX_SYMLINKS,
},
Fd, WasiEnv, WasiError, WasiThread, WasiThreadId,
};
@@ -1804,9 +1804,7 @@ pub fn fd_pipe<M: MemorySize>(
let env = ctx.data();
let (memory, state, mut inodes) = env.get_memory_and_wasi_state_and_inodes_mut(&ctx, 0);
let pipes = WasiBidirectionalPipePair::new();
let pipe1 = pipes.send;
let pipe2 = pipes.recv;
let (pipe1, pipe2) = WasiPipe::new();
let inode1 = state.fs.create_inode_with_default_stat(
inodes.deref_mut(),

View File

@@ -1,7 +1,7 @@
use std::io::{Read, Write};
use wasmer::{Instance, Module, Store};
use wasmer_wasi::{WasiBidirectionalSharedPipePair, WasiState};
use wasmer_wasi::{Pipe, WasiState};
mod sys {
#[test]
@@ -73,10 +73,10 @@ fn test_stdout() {
"#).unwrap();
// Create the `WasiEnv`.
let mut pipe = WasiBidirectionalSharedPipePair::new().with_blocking(false);
let mut stdout = Pipe::default();
let wasi_env = WasiState::new("command-name")
.args(&["Gordon"])
.stdout(Box::new(pipe.clone()))
.stdout(Box::new(stdout.clone()))
.finalize(&mut store)
.unwrap();
@@ -93,7 +93,7 @@ fn test_stdout() {
start.call(&mut store, &[]).unwrap();
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();
assert_eq!(stdout_as_str, "hello world\n");
}
@@ -110,7 +110,7 @@ fn test_env() {
});
// 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");
wasi_state_builder
.args(&["Gordon"])
@@ -119,7 +119,7 @@ fn test_env() {
.env("TEST2", "VALUE2");
// panic!("envs: {:?}", wasi_state_builder.envs);
let wasi_env = wasi_state_builder
.stdout(Box::new(pipe.clone()))
.stdout(Box::new(stdout.clone()))
.finalize(&mut store)
.unwrap();
@@ -136,7 +136,7 @@ fn test_env() {
start.call(&mut store, &[]).unwrap();
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();
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();
// 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
let buf = "Hello, stdin!\n".as_bytes().to_owned();
pipe.write(&buf[..]).unwrap();
let wasi_env = WasiState::new("command-name")
.stdin(Box::new(pipe.clone()))
.finalize(&mut store)
.unwrap();
stdin.write(&buf[..]).unwrap();
// Generate an `ImportObject`.
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 start = instance.exports.get_function("_start").unwrap();
let result = start.call(&mut store, &[]);
assert!(result.is_ok());
assert!(!result.is_err());
// We assure stdin is now empty
let mut buf = Vec::new();
pipe.read_to_end(&mut buf).unwrap();
stdin.read_to_end(&mut buf).unwrap();
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 output: Vec<u8> = WasmerCreateObj {
current_dir: operating_dir,
current_dir: operating_dir.clone(),
wasm_path,
output_object_path: object_path.clone(),
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",
object_path.display()
);
let mut object_header_path = object_path;
let mut object_header_path = object_path.clone();
object_header_path.set_extension("h");
assert!(
object_header_path.exists(),

View File

@@ -40,8 +40,9 @@ mod tests {
*/
let command_success = command.status.success();
let test_success = !stderr.contains("** TEST FAILED **");
let success = command_success && test_success;
command_success && test_success
success
}
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_wasi::types::wasi::{Filesize, Timestamp};
use wasmer_wasi::{
generate_import_object_from_env, get_wasi_version, FsError, VirtualFile,
WasiBidirectionalPipePair, WasiEnv, WasiFunctionEnv, WasiState, WasiVersion,
generate_import_object_from_env, get_wasi_version, FsError, Pipe, VirtualFile, WasiEnv,
WasiFunctionEnv, WasiState, WasiVersion,
};
use wast::parser::{self, Parse, ParseBuffer, Parser};
@@ -142,7 +142,7 @@ impl<'a> WasiTest<'a> {
)> {
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));
for (name, value) in &self.envs {