【问题标题】:Caller/Backtrace beyond a thread线程之外的调用者/回溯
【发布时间】:2014-05-23 10:38:55
【问题描述】:

据我所知,只能获取当前线程内的调用者/回溯信息的一部分;在此之前的任何内容(在创建当前线程的线程中)都会被切断。以下举例说明了这一点; 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. 有没有办法在当前线程之外获取调用者/回溯信息?

【问题讨论】:

    标签: ruby multithreading backtrace


    【解决方案1】:

    我想我想出了我的答案。

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

    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 或创建可能是有意义的。这取决于定义。

    【讨论】:

      【解决方案2】:

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

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

      简而言之:

      1. 产生线程的堆栈不会保持在产生线程时的状态,因此从线程自己的堆栈开始返回是不安全的。

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

      更新:

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

      1. 线程创建会变慢。如果可以从中获得任何好处,那还可以,但是在这种情况下,是吗?

      2. 从线程入口函数返回是什么意思?

        • 它可以返回到创建线程的函数并继续运行,就好像它只是一个函数调用一样——只是它现在运行在第二个线程中,而不是原来的线程中。我们想要吗?
        • 可能有一些魔法可以确保线程终止,即使它不在调用堆栈的顶部。无论如何,这会使线程入口函数上方的调用堆栈中的信息不正确。
      3. 在每个线程的堆栈大小有限制的系统上,您可能会遇到线程用尽堆栈的问题,即使它自己并没有使用太多。

      可能还可以考虑其他场景和特性,但线程创建时使用自己的空堆栈的方式使模型既简单又可预测,而不会从调用堆栈中留下任何有用的信息。

      【讨论】:

      • 你的回答解释了为什么当前的实现不能返回信息。但原则上我认为这是不可能的。如果每个线程在创建时将调用者信息复制到创建它的那一刻,并将其保存在自己内部,那么是否有可能从该线程中获取全部信息?我错了吗?我觉得我什至可以在 Ruby 级别实现它。
      • 没有什么是不可能的,但有什么收获吗?请更新答案。
      猜你喜欢
      • 2016-12-30
      • 2015-08-14
      • 1970-01-01
      • 2012-02-21
      • 2015-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多