Limiting Run Time
Track Progress and Force-Termination
Operations count does not indicate the proportion of work already done – thus it is not real progress tracking.
The real progress can be estimated based on the expected number of operations in a typical run.
It is impossible to know when, or even whether, a script run will end (a.k.a. the Halting Problem).
When dealing with third-party untrusted scripts that may be malicious, in order to track evaluation
progress and force-terminate a script prematurely (for any reason), provide a closure to the
Engine
via Engine::on_progress
.
The closure passed to Engine::on_progress
will be called once for every operation.
Progress tracking is disabled with the unchecked
feature.
Examples
Periodic Logging
let mut engine = Engine::new();
engine.on_progress(|count| { // parameter is number of operations already performed
if count % 1000 == 0 {
println!("{count}"); // print out a progress log every 1,000 operations
}
None // return 'None' to continue running the script
// return 'Some(token)' to immediately terminate the script
});
Limit running time
let mut engine = Engine::new();
let start = get_time(); // get the current system time
engine.on_progress(move |_| {
let now = get_time();
if now.duration_since(start).as_secs() > 60 {
// Return a dummy token just to force-terminate the script
// after running for more than 60 seconds!
Some(Dynamic::UNIT)
} else {
// Continue
None
}
});
Function Signature of Callback
The signature of the closure to pass to Engine::on_progress
is as follows.
Fn(operations: u64) -> Option<Dynamic>
Return value
Value | Effect |
---|---|
Some(token) | terminate immediately, with token (a Dynamic value) as termination token |
None | continue script evaluation |
Termination Token
The termination token is commonly used to provide information on the reason behind the termination decision.
The Dynamic
value returned is a termination token.
A script that is manually terminated returns with the error EvalAltResult::ErrorTerminated(token, position)
wrapping this value.
If the termination token is not needed, simply return Some(Dynamic::UNIT)
to terminate the script
run with ()
as the token.