Silverlight 中中断解释的用户代码

发布于 2024-12-12 17:10:38 字数 508 浏览 0 评论 0原文

我想在 Silverlight 应用程序中运行一些任意用户代码。当然,我想嵌入图灵完备的语言(足够简单),但不想让用户在编写一些糟糕的(非终止的)代码时锁定他们的浏览器。我并不是要求解决 停止问题,只需在后台线程上运行此用户代码并按一下按钮即可终止它。

即使我想在Silverlight中使用Thread.Abort也无法使用,那么如何中断后台解释器线程呢?

我当前的想法:

  • 如果我手动解释某种语言,当然我可以在需要时停止执行
  • 我可以使用 Reflection.Emit 或编译表达式树,并插入类似的检查以提前终止
  • 修改现有编译器以生成执行以下操作的代码这个(也许是 F# 或 IronPython?)
  • 由现有工具生成的后处理 IL(这是否排除了基于 DLR 的语言?)

我不禁认为必须有一个更简单的解决方案。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

任性一次 2024-12-19 17:10:38

修改 IronPython 或 IronRuby 来做到这一点并不会太困难。最终,您只需要编写一个 ExpressionVisitor,它在后面的分支(循环,也许 gotos)和方法调用中插入轮询。这应该非常简单,例如处理循环可能如下所示:

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 {
}

对于 IronPython,您可以在构造 FunctionCode 对象时提供的 lambda 上运行此表达式访问者。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文