当线程在C中调用longjmp()时会发生什么

时间:2019-06-06 21:35:51

标签: c multithreading thread-safety pthreads

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

  1. 如果在线程内部调用了setjmp,然后又调用了longjmp,那么一切都可以吗?
  2. 如果setjmp在任何线程存在之前被调用,然后一个线程在该longjmp上调用jmp_buf怎么办,它会杀死所有其他线程,因为当{ {1}}已创建?

2 个答案:

答案 0 :(得分:4)

有关功能的POSIX规范可在以下网址找到:

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

  

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

针对您的情况:

  1. 应该可以。
  2. 未定义的行为。相反,如果主线程(或称为setjmp()的线程)执行了longjmp(),则应该可以,但不会杀死其他线程。即使如此,您仍可能会违反longjmp()上的一般限制。

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

答案 1 :(得分:3)

我要让语言律师肯定地说,但是我怀疑,如果您尝试将longjmp()从一个线程转换为另一个线程创建的jmp_buf,则会导致未定义的行为

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

在地球上,这种情况不可能完全解决。