调用者/ Backtrace超越线程

时间:2014-05-23 10:38:55

标签: ruby multithreading backtrace

据我所知,有可能只得到当前线程中的调用者/回溯信息部分;之前的任何事情(在创建当前线程的线程中)都被切断了。以下举例说明这一点; a调用b,调用c,创建调用d的线程的事实被切断了:

def a; b end
def b; c end
def c; Thread.new{d}.join end
def d; e end
def e; puts caller end

a
# => this_file:4:in `d'
#    this_file:3:in `block in c'
  1. 此功能的原因是什么?
  2. 有没有办法让调用者/回溯信息超出当前线程?

2 个答案:

答案 0 :(得分:0)

你的两个问题的答案都是一样的。考虑一个稍微复杂一点的主线程。而不是简单地等待生成的线程以c结束,主线程继续调用其他函数,甚至可能从c返回并在生成的线程继续进行时开始它的业务。它的业务。

这意味着自从d开始生成的线程产生后,主线程中的堆栈发生了变化。换句话说,当您调用puts caller时,主线程中的堆栈不再处于创建辅助线程时的状态。超过这一点,没有办法安全地向上走回堆栈。

简而言之:

  1. 产生线程的堆栈不会保持在线程生成时的状态,因此回退到线程自身堆栈的开头是不安全的。

  2. 不,因为线程背后的整个想法是(伪)并行,所以它们的堆栈完全不相关。

  3. <强>更新

    正如评论中所建议的那样,当前线程的堆栈可以在创建时复制到新线程。这将保留导致正在创建的线程的信息,但解决方案并非没有自己的一组问题。

    1. 线程创建速度会变慢。那可能没问题,如果有什么可以从中获益,但在这种情况下,是吗?

    2. 从线程输入功能返回是什么意思?

      • 它可以返回到创建线程的函数并继续运行,好像它只是一个函数调用 - 只是它现在在第二个线程中运行,而不是原始线程。我们想要吗?
      • 可能有一些魔力确保线程终止,即使它不在调用堆栈的顶部。这将使得线程入口函数上方的调用堆栈中的信息无论如何都是错误的。
    3. 在对每个线程的stacksize有限制的系统上,你可能会遇到线程耗尽堆栈的问题,即使它没有在它上面使用很多东西。
    4. 可能还有其他一些场景和特性也可以考虑,但是线程是用自己的空堆栈创建的,这使得模型既简单又可预测,而不会从callstack中留下任何有用的信息。

答案 1 :(得分:0)

我想我想出了答案。

可以从线程外部对线程执行的操作不仅仅是创建它。除了创建之外,您还可以唤醒等等。因此,不清楚应将哪些操作归因于调用者。例如,假设有一个帖子:

1: t = Thread.new{
2:   Thread.stop
3:   puts caller
4: }
5: t.wakeup

线程t在第1行创建,但它在第2行自行进入睡眠状态,然后由第5行唤醒。因此,当我们将自己定位在第3行caller时,并且考虑线程外部的调用者部分,不清楚第1行中的Thread.new是否应该是其中的一部分,或者第5行中的t.wakeup应该是其中的一部分。因此,除了当前的线程之外,没有明确的概念调用者。

但是,如果我们定义一个明确的概念,那么调用者可能超出一个线程是有意义的。例如,始终将调用者添加到线程的创建可能是有意义的。否则,添加导致最新wakeup或创建的呼叫者可能有意义。这取决于定义。