Expose TrapCode::Interrupt on epoch based interruption (#4105)
This commit is contained in:
@@ -593,7 +593,7 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
|
|||||||
// The reason is that one can construct a "zip-bomb-like"
|
// The reason is that one can construct a "zip-bomb-like"
|
||||||
// program with exponential-in-program-size runtime, with no
|
// program with exponential-in-program-size runtime, with no
|
||||||
// backedges (loops), by building a tree of function calls: f0
|
// backedges (loops), by building a tree of function calls: f0
|
||||||
// calls f1 ten tims, f1 calls f2 ten times, etc. E.g., nine
|
// calls f1 ten times, f1 calls f2 ten times, etc. E.g., nine
|
||||||
// levels of this yields a billion function calls with no
|
// levels of this yields a billion function calls with no
|
||||||
// backedges. So we can't do checks only at backedges.
|
// backedges. So we can't do checks only at backedges.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1856,7 +1856,14 @@ unsafe impl<T> wasmtime_runtime::Store for StoreInner<T> {
|
|||||||
|
|
||||||
fn new_epoch(&mut self) -> Result<u64, anyhow::Error> {
|
fn new_epoch(&mut self) -> Result<u64, anyhow::Error> {
|
||||||
return match &self.epoch_deadline_behavior {
|
return match &self.epoch_deadline_behavior {
|
||||||
&EpochDeadline::Trap => Err(anyhow::Error::new(EpochDeadlineError)),
|
&EpochDeadline::Trap => {
|
||||||
|
let trap = Trap::new_wasm(
|
||||||
|
None,
|
||||||
|
wasmtime_environ::TrapCode::Interrupt,
|
||||||
|
wasmtime_runtime::Backtrace::new(),
|
||||||
|
);
|
||||||
|
Err(anyhow::Error::from(trap))
|
||||||
|
}
|
||||||
#[cfg(feature = "async")]
|
#[cfg(feature = "async")]
|
||||||
&EpochDeadline::YieldAndExtendDeadline { delta } => {
|
&EpochDeadline::YieldAndExtendDeadline { delta } => {
|
||||||
// Do the async yield. May return a trap if future was
|
// Do the async yield. May return a trap if future was
|
||||||
@@ -1870,17 +1877,6 @@ unsafe impl<T> wasmtime_runtime::Store for StoreInner<T> {
|
|||||||
Ok(self.get_epoch_deadline())
|
Ok(self.get_epoch_deadline())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct EpochDeadlineError;
|
|
||||||
|
|
||||||
impl fmt::Display for EpochDeadlineError {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
f.write_str("epoch deadline reached during execution")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::error::Error for EpochDeadlineError {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ fn main() -> Result<()> {
|
|||||||
let trap = run.call(&mut store, ()).unwrap_err();
|
let trap = run.call(&mut store, ()).unwrap_err();
|
||||||
|
|
||||||
println!("trap received...");
|
println!("trap received...");
|
||||||
assert!(trap.to_string().contains("epoch deadline reached"));
|
assert!(trap.trap_code().unwrap() == TrapCode::Interrupt);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ fn timeout_in_start() -> Result<()> {
|
|||||||
assert_eq!(output.stdout, b"");
|
assert_eq!(output.stdout, b"");
|
||||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||||
assert!(
|
assert!(
|
||||||
stderr.contains("epoch deadline reached during execution"),
|
stderr.contains("wasm trap: interrupt"),
|
||||||
"bad stderr: {}",
|
"bad stderr: {}",
|
||||||
stderr
|
stderr
|
||||||
);
|
);
|
||||||
@@ -196,7 +196,7 @@ fn timeout_in_invoke() -> Result<()> {
|
|||||||
assert_eq!(output.stdout, b"");
|
assert_eq!(output.stdout, b"");
|
||||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||||
assert!(
|
assert!(
|
||||||
stderr.contains("epoch deadline reached during execution"),
|
stderr.contains("wasm trap: interrupt"),
|
||||||
"bad stderr: {}",
|
"bad stderr: {}",
|
||||||
stderr
|
stderr
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ fn loops_interruptable() -> anyhow::Result<()> {
|
|||||||
store.engine().increment_epoch();
|
store.engine().increment_epoch();
|
||||||
let trap = iloop.call(&mut store, ()).unwrap_err();
|
let trap = iloop.call(&mut store, ()).unwrap_err();
|
||||||
assert!(
|
assert!(
|
||||||
trap.to_string().contains("epoch deadline reached"),
|
trap.trap_code().unwrap() == TrapCode::Interrupt,
|
||||||
"bad message: {}",
|
"bad message: {}",
|
||||||
trap
|
trap
|
||||||
);
|
);
|
||||||
@@ -50,7 +50,7 @@ fn functions_interruptable() -> anyhow::Result<()> {
|
|||||||
store.engine().increment_epoch();
|
store.engine().increment_epoch();
|
||||||
let trap = iloop.call(&mut store, ()).unwrap_err();
|
let trap = iloop.call(&mut store, ()).unwrap_err();
|
||||||
assert!(
|
assert!(
|
||||||
trap.to_string().contains("epoch deadline reached"),
|
trap.trap_code().unwrap() == TrapCode::Interrupt,
|
||||||
"{}",
|
"{}",
|
||||||
trap.to_string()
|
trap.to_string()
|
||||||
);
|
);
|
||||||
@@ -103,7 +103,7 @@ fn loop_interrupt_from_afar() -> anyhow::Result<()> {
|
|||||||
thread.join().unwrap();
|
thread.join().unwrap();
|
||||||
assert!(HITS.load(SeqCst) > NUM_HITS);
|
assert!(HITS.load(SeqCst) > NUM_HITS);
|
||||||
assert!(
|
assert!(
|
||||||
trap.to_string().contains("epoch deadline reached"),
|
trap.trap_code().unwrap() == TrapCode::Interrupt,
|
||||||
"bad message: {}",
|
"bad message: {}",
|
||||||
trap.to_string()
|
trap.to_string()
|
||||||
);
|
);
|
||||||
@@ -143,7 +143,7 @@ fn function_interrupt_from_afar() -> anyhow::Result<()> {
|
|||||||
thread.join().unwrap();
|
thread.join().unwrap();
|
||||||
assert!(HITS.load(SeqCst) > NUM_HITS);
|
assert!(HITS.load(SeqCst) > NUM_HITS);
|
||||||
assert!(
|
assert!(
|
||||||
trap.to_string().contains("epoch deadline reached"),
|
trap.trap_code().unwrap() == TrapCode::Interrupt,
|
||||||
"bad message: {}",
|
"bad message: {}",
|
||||||
trap.to_string()
|
trap.to_string()
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user