Interrupt interpreted user code in Silverlight

144 views Asked by At

I'd like to run some arbitrary user code in a Silverlight application. Of course I want to embed a Turing-complete language (easy enough), but don't want to allow the user to lock up their browser if they write some bad (non-terminating) code. I'm not asking to solve the Halting Problem, just run this user code on a background thread and terminate it at the press of a button.

I can't use Thread.Abort in Silverlight even if I want to, so how can I interrupt the background interpreter thread?

My current ideas:

  • If I interpret some language by hand, of course I can stop execution when I want
  • I could use Reflection.Emit or compile an expression tree, and insert similar checks to do early termination
  • Modify an existing compiler to generate code that does this (F# or IronPython maybe?)
  • Postprocess IL generated by an existing tool (Does this rule out DLR based languages?)

I can't help think there has to be a simpler solution.

1

There are 1 answers

0
Dino Viehland On BEST ANSWER

Modifying IronPython or IronRuby to do this wouldn't be too difficult. Ultimately you'll just need to write a ExpressionVisitor which inserts polling at back branches (loops, maybe gotos) and method calls. This should be pretty easy, for example handling loops could look like:

public class AbortPollRewriter : ExpressionVisitor {
    protected override Expression VisitLoop(LoopExpression node) {
        var body = Expression.Block(
            Expression.Call(typeof(AbortPollRewriter).GetMethod("Poll")),
            node.Body
        );
        return Expression.Loop(body, node.BreakLabel, node.ContinueLabel);
    }

    [ThreadStatic]
    private static bool _aborting;

    public static void Abort() {
        _aborting = true;
    }

    public static void Poll() {
        if (_aborting) {
            throw new MyThreadAbortException();
        }
    }
}

class MyThreadAbortException : Exception {
}

For IronPython you could then run this expression visitor on the lambda provided when FunctionCode objects are constructed.