【问题标题】:What happens when a thread calls longjmp() in c当线程在 c 中调用 longjmp() 时会发生什么
【发布时间】:2019-10-22 10:24:36
【问题描述】:

当您有一个在 c 语言中调用 longjmp 的线程时会发生什么。我知道当程序在单个线程上时,PC 会被放回创建jmp_buf 时的地址,并且处理器的寄存器会恢复到那个时间点。

  1. 如果在线程内部调用了setjmp,然后又调用了longjmp,那么一切都可能正常吗?
  2. 如果在任何线程存在之前调用setjmp,然后一个线程在该jmp_buf 上调用longjmp,它是否会杀死所有其他线程,因为在创建jmp_buf 时它们不存在?

【问题讨论】:

    标签: c multithreading thread-safety pthreads


    【解决方案1】:

    我会让语言律师肯定地说,但我怀疑如果您尝试将 longjmp() 从一个线程转到另一个线程创建的 jmp_buf,这将导致不确定的行为。

    我这样做的原因是这两个线程通常会有完全不同的堆栈,并且至少在 MSVC x64 上,setjmp() 保存了 rbprsp,它们是指向当前堆栈的指针。这样做的最终结果是调用longjmp() 的线程将从setjmp() 出来,它的堆栈指针和帧指针指向另一个线程的堆栈中间。

    在地球上,这种情况不可能有好的结局。

    【讨论】:

    • 我的想法完全是关于结局不好的事情。有人可能会争辩说,在 C 语言的底层并没有太多你无法控制的事情,但像这样的一些具体事情可能有点神秘。
    【解决方案2】:

    相关函数的 POSIX 规范可以在以下位置找到:

    请注意,longjmp() 的规范列出了一些限制:

    longjmp() 函数应使用相应的jmp_buf 参数恢复同一进程中最近一次调用setjmp() 保存的环境。如果最近一次调用 setjmp() 和对应的 jmp_buf 发生在另一个线程中,或者如果没有这样的调用,或者如果包含 setjmp() 调用的函数在中间终止了执行,或者如果调用的setjmp() 在具有可变修改类型的标识符的范围内,并且执行在过渡期间离开了该范围,行为未定义。 [CX] ⌦ 未指定 longjmp() 是恢复信号掩码,保持信号掩码不变,还是将其恢复为调用 setjmp() 时的值。 ⌫

    对于您的场景:

    1. 应该没问题。
    2. 未定义的行为。如果相反,主线程(或调用setjmp() 的线程)执行longjmp(),应该没问题,但它不会杀死其他线程。即使如此,您也可能会违反对 longjmp() 的一般限制。

    总体而言,要明智且非常保守。它们是脆弱的功能。除非真的有必要,否则不要使用它们,并且通常要担心资源管理。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-13
      • 2017-02-14
      • 1970-01-01
      • 2011-01-18
      • 2013-06-09
      • 1970-01-01
      • 2019-02-11
      • 2012-05-17
      相关资源
      最近更新 更多