在中断期间调用的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>
的两个实例。它们以某种方式结合在一起。我不确定如何。此外,当有多个线程运行时会发生什么?如何确定在中断调用的调用堆栈中哪些线程被组合或忽略?
答案 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'