use virtual stdio
which works except for the lifetime issues, i think the trap still holds an Rc to the store?
This commit is contained in:
@@ -2,49 +2,71 @@ use anyhow::Context;
|
|||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use wasi_c2::WasiCtx;
|
use wasi_c2::{
|
||||||
|
virt::pipe::{ReadPipe, WritePipe},
|
||||||
|
WasiCtx,
|
||||||
|
};
|
||||||
use wasmtime::{Linker, Module, Store};
|
use wasmtime::{Linker, Module, Store};
|
||||||
|
|
||||||
pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> anyhow::Result<()> {
|
pub fn instantiate(data: &[u8], bin_name: &str, workspace: Option<&Path>) -> anyhow::Result<()> {
|
||||||
let store = Store::default();
|
let stdout = WritePipe::new_in_memory();
|
||||||
|
let stderr = WritePipe::new_in_memory();
|
||||||
|
|
||||||
// Create our wasi context with pretty standard arguments/inheritance/etc.
|
let r = {
|
||||||
// Additionally register any preopened directories if we have them.
|
let store = Store::default();
|
||||||
let mut builder = wasi_c2::WasiCtx::builder();
|
|
||||||
|
|
||||||
builder.arg(bin_name)?.arg(".")?.inherit_stdio();
|
// Create our wasi context.
|
||||||
|
// Additionally register any preopened directories if we have them.
|
||||||
|
let mut builder = wasi_c2::WasiCtx::builder();
|
||||||
|
|
||||||
if let Some(workspace) = workspace {
|
builder
|
||||||
let dirfd =
|
.arg(bin_name)?
|
||||||
File::open(workspace).context(format!("error while preopening {:?}", workspace))?;
|
.arg(".")?
|
||||||
let preopen_dir = unsafe { cap_std::fs::Dir::from_std_file(dirfd) };
|
.stdin(Box::new(ReadPipe::from(Vec::new())))
|
||||||
builder.preopened_dir(Box::new(preopen_dir), ".")?;
|
.stdout(Box::new(stdout.clone()))
|
||||||
|
.stderr(Box::new(stderr.clone()));
|
||||||
|
|
||||||
|
if let Some(workspace) = workspace {
|
||||||
|
let dirfd =
|
||||||
|
File::open(workspace).context(format!("error while preopening {:?}", workspace))?;
|
||||||
|
let preopen_dir = unsafe { cap_std::fs::Dir::from_std_file(dirfd) };
|
||||||
|
builder.preopened_dir(Box::new(preopen_dir), ".")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let snapshot1 = wasi_c2_wasmtime::Wasi::new(&store, builder.build()?);
|
||||||
|
|
||||||
|
let mut linker = Linker::new(&store);
|
||||||
|
|
||||||
|
snapshot1.add_to_linker(&mut linker)?;
|
||||||
|
|
||||||
|
let module = Module::new(store.engine(), &data).context("failed to create wasm module")?;
|
||||||
|
|
||||||
|
linker
|
||||||
|
.module("", &module)
|
||||||
|
.and_then(|m| m.get_default(""))
|
||||||
|
.and_then(|f| f.get0::<()>())
|
||||||
|
.and_then(|f| f().map_err(Into::into))
|
||||||
|
};
|
||||||
|
match r {
|
||||||
|
Ok(()) => Ok(()),
|
||||||
|
Err(trap) => {
|
||||||
|
let stdout = stdout
|
||||||
|
.try_into_inner()
|
||||||
|
.expect("sole ref to stdout")
|
||||||
|
.into_inner();
|
||||||
|
if !stdout.is_empty() {
|
||||||
|
println!("guest stdout:\n{}\n===", String::from_utf8_lossy(&stdout));
|
||||||
|
}
|
||||||
|
let stderr = stderr
|
||||||
|
.try_into_inner()
|
||||||
|
.expect("sole ref to stderr")
|
||||||
|
.into_inner();
|
||||||
|
if !stderr.is_empty() {
|
||||||
|
println!("guest stderr:\n{}\n===", String::from_utf8_lossy(&stderr));
|
||||||
|
}
|
||||||
|
Err(trap.context(format!("error while testing Wasm module '{}'", bin_name,)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// The nonstandard thing we do with `WasiCtxBuilder` is to ensure that
|
|
||||||
// `stdin` is always an unreadable pipe. This is expected in the test suite
|
|
||||||
// where `stdin` is never ready to be read. In some CI systems, however,
|
|
||||||
// stdin is closed which causes tests to fail.
|
|
||||||
let (reader, _writer) = os_pipe::pipe()?;
|
|
||||||
let file = reader_to_file(reader);
|
|
||||||
let handle = OsOther::try_from(file).context("failed to create OsOther from PipeReader")?;
|
|
||||||
builder.stdin(handle);
|
|
||||||
*/
|
|
||||||
let snapshot1 = wasi_c2_wasmtime::Wasi::new(&store, builder.build()?);
|
|
||||||
|
|
||||||
let mut linker = Linker::new(&store);
|
|
||||||
|
|
||||||
snapshot1.add_to_linker(&mut linker)?;
|
|
||||||
|
|
||||||
let module = Module::new(store.engine(), &data).context("failed to create wasm module")?;
|
|
||||||
|
|
||||||
linker
|
|
||||||
.module("", &module)
|
|
||||||
.and_then(|m| m.get_default(""))
|
|
||||||
.and_then(|f| f.get0::<()>())
|
|
||||||
.and_then(|f| f().map_err(Into::into))
|
|
||||||
.context(format!("error while testing Wasm module '{}'", bin_name,))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
|
|||||||
@@ -69,31 +69,48 @@ impl WasiCtxBuilder {
|
|||||||
pub fn build(self) -> Result<WasiCtx, Error> {
|
pub fn build(self) -> Result<WasiCtx, Error> {
|
||||||
Ok(self.0)
|
Ok(self.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn arg(&mut self, arg: &str) -> Result<&mut Self, StringArrayError> {
|
pub fn arg(&mut self, arg: &str) -> Result<&mut Self, StringArrayError> {
|
||||||
self.0.args.push(arg.to_owned())?;
|
self.0.args.push(arg.to_owned())?;
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
pub fn inherit_stdio(&mut self) -> &mut Self {
|
|
||||||
|
pub fn stdin(&mut self, f: Box<dyn WasiFile>) -> &mut Self {
|
||||||
self.0.insert_file(
|
self.0.insert_file(
|
||||||
0,
|
0,
|
||||||
Box::new(crate::stdio::stdin()),
|
f,
|
||||||
FileCaps::READ,
|
FileCaps::READ, // XXX probably more rights are ok
|
||||||
FileCaps::READ,
|
FileCaps::READ,
|
||||||
);
|
);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stdout(&mut self, f: Box<dyn WasiFile>) -> &mut Self {
|
||||||
self.0.insert_file(
|
self.0.insert_file(
|
||||||
1,
|
1,
|
||||||
Box::new(crate::stdio::stdout()),
|
f,
|
||||||
FileCaps::WRITE,
|
FileCaps::WRITE, // XXX probably more rights are ok
|
||||||
FileCaps::WRITE,
|
|
||||||
);
|
|
||||||
self.0.insert_file(
|
|
||||||
2,
|
|
||||||
Box::new(crate::stdio::stderr()),
|
|
||||||
FileCaps::WRITE,
|
|
||||||
FileCaps::WRITE,
|
FileCaps::WRITE,
|
||||||
);
|
);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn stderr(&mut self, f: Box<dyn WasiFile>) -> &mut Self {
|
||||||
|
self.0.insert_file(
|
||||||
|
2,
|
||||||
|
f,
|
||||||
|
FileCaps::WRITE, // XXX probably more rights are ok
|
||||||
|
FileCaps::WRITE,
|
||||||
|
);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn inherit_stdio(&mut self) -> &mut Self {
|
||||||
|
self.stdin(Box::new(crate::stdio::stdin()))
|
||||||
|
.stdout(Box::new(crate::stdio::stdout()))
|
||||||
|
.stderr(Box::new(crate::stdio::stderr()))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn preopened_dir(
|
pub fn preopened_dir(
|
||||||
&mut self,
|
&mut self,
|
||||||
dir: Box<dyn WasiDir>,
|
dir: Box<dyn WasiDir>,
|
||||||
|
|||||||
Reference in New Issue
Block a user