Is your feature request related to a problem? Please describe.
When embedding SCI as a sandboxed evaluator, there's currently no built-in way to bound execution time, iteration count, or memory usage per context. Runaway user scripts — infinite loops, deep recursion, unbounded reduce — can consume the host JVM's thread indefinitely, requiring coarse external mechanisms like thread interruption or a global timeout that apply across all contexts equally.
Describe the solution you'd like
An optional :interrupt-fn callback in the SCI context options. When provided, it is called on every function entry (covering loops, dotimes, while, direct recursion, and mutual recursion). The function can throw to abort execution. Because it's captured at function-creation time as a closed-over local, the check is a free nil test when not configured — zero overhead for existing users.
This enables per-context limits: iteration counts, JVM-allocated-bytes checks (ThreadMXBean.getThreadAllocatedBytes), or Thread/interrupted polls, each with independent thresholds per sandbox.
Describe alternatives you've considered
- External thread interruption: works but is global and requires managing threads explicitly.
- A global step counter: no per-context isolation.
- Fuel/quota passed through the interpreter: would require invasive changes to every eval site.
Is your feature request related to a problem? Please describe.
When embedding SCI as a sandboxed evaluator, there's currently no built-in way to bound execution time, iteration count, or memory usage per context. Runaway user scripts — infinite loops, deep recursion, unbounded reduce — can consume the host JVM's thread indefinitely, requiring coarse external mechanisms like thread interruption or a global timeout that apply across all contexts equally.
Describe the solution you'd like
An optional
:interrupt-fncallback in the SCI context options. When provided, it is called on every function entry (covering loops, dotimes, while, direct recursion, and mutual recursion). The function can throw to abort execution. Because it's captured at function-creation time as a closed-over local, the check is a free nil test when not configured — zero overhead for existing users.This enables per-context limits: iteration counts, JVM-allocated-bytes checks (
ThreadMXBean.getThreadAllocatedBytes), orThread/interruptedpolls, each with independent thresholds per sandbox.Describe alternatives you've considered