打电话给中断

时间:2012-10-22 03:31:17

标签: ruby interrupt

在中断期间调用的caller内容的规则是什么?当我运行以下代码时:

File: test

1| def a; b end
2| def b; c end
3| def c; loop{sleep(1)} end
4| def d; e end
5| def e; f end
6| def f; puts caller; exit end
7| Signal.trap("INT"){d}
8| a

并在执行期间输入Ctrl+c,我得到以下输出:

test:5:in `e'
test:4:in `d'
test:7:in `block in <main>'
test:3:in `call'
test:3:in `sleep'
test:3:in `block in c'
test:3:in `loop'
test:3:in `c'
test:2:in `b'
test:1:in `a'
test:8:in `<main>'

组成此调用堆栈的规则是什么?我看到<main>的两个实例。它们以某种方式结合在一起。我不确定如何。此外,当有多个线程运行时会发生什么?如何确定在中断调用的调用堆栈中哪些线程被组合或忽略?

1 个答案:

答案 0 :(得分:0)

我不确定你在寻找什么“规则”。信号是由ruby运行时异步接收并排队的;在每个基本执行步骤(1.8中的AST节点,YARV中的字节码指令)之间,运行时检查是否存在未决信号并为它们调用绑定处理程序。调用处理程序不会修改先前存在的调用堆栈。如果你的处理程序要返回,程序执行将在它停止的地方再次启动。

以下是您的示例所展示的执行流程:在main中,您调用Signal.trap将其移交给在main中定义的块{d}。然后,您拨打a,呼叫b,呼叫c,该呼叫始终循环调用c {sleep(1)}中定义的调用sleep的阻止。

发送SIGINT并且运行时接收信号并调用您注册为INT处理程序的块(test:7:in 'block in <main>'),调用d,调用e,调用f {1}},打印您看到并退出的调用堆栈。

由于大部分时间都是在睡眠中度过的,因此这是调用INT处理程序的最可能的执行点。但是,如果INT信号恰到好处,您可能会看到相同的调用堆栈,其中一行或两行都被省略:

test:3:in `sleep'
test:3:in `block in c'