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

What happens when a thread calls longjmp() in c

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

  1. 如果在线程内部调用了setjmp,然后又调用了longjmp,是不是就没问题了?
  2. 如果在任何线程存在之前调用 setjmp,然后一个线程在那个 jmp_buf 上调用 longjmp,它会杀死所有其他线程吗,因为它们在什么时候不存在jmp_buf 已创建?

我要让语言律师确定,但我怀疑如果您尝试从线程 longjmp() 到由线程创建的 jmp_buf 会导致未定义的行为不同的线程。

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

地球上没有办法让这种情况有好的结束。

相关功能的 POSIX 规范可在以下位置找到:

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

The longjmp() function shall restore the environment saved by the most recent invocation of setjmp() in the same process, with the corresponding jmp_buf argument. If the most recent invocation of setjmp() with the corresponding jmp_buf occurred in another thread, or if there is no such invocation, or if the function containing the invocation of setjmp() has terminated execution in the interim, or if the invocation of setjmp() was within the scope of an identifier with variably modified type and execution has left that scope in the interim, the behavior is undefined. [CX] ⌦ It is unspecified whether longjmp() restores the signal mask, leaves the signal mask unchanged, or restores it to its value at the time setjmp() was called. ⌫

对于您的场景:

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

总的来说,很理智,也很保守。它们是脆弱的功能。除非真的有必要,否则不要使用它们,并担心一般的资源管理。