fork() 内崩溃;从不同的线程分叉消除了崩溃

Crash inside fork(); forking from a different thread eliminates the crash

TLDR:在下面概述的情况下,如果我调用 fork() 它会崩溃。如果我 fork() 在一个新线程上,它会 而不是 崩溃。他们在做什么会导致 fork() 崩溃?


我正在研究在 vxsim(一个 VxWorks 仿真环境)中运行的东西,在探索它的一些限制时我 运行 解决了这个问题。

vxsim 作为单线程进程运行,具有自己的内部任务调度程序。它使用 itimer() (SIGALRM) 来模拟适当的中断,在此期间它使用 setcontext() (在 Solaris 中;在 Linux 中它做类似的事情)使当前(仅)线程在不同的任务上恢复执行。

“sim”函数和“host”函数之间几乎没有真正的区别。 ABI 是相同的;如果您碰巧有主机函数的地址(例如,fork()),则可以直接调用它。 唯一的问题是应该首先调用一个函数来禁用模拟中断等。

作为一项实验,我让它调用了 fork(),但它在调用期间崩溃了。相反,如果我创建一个新线程,那么 fork() 在新线程上它不会崩溃。

模拟在 x86 Linux 和 sparc Solaris 10 上都是这样。

为了比较,我在更旧版本的 VxWorks (5.x) 中做了同样的事情,它工作得很好。

我要找的是这个问题的答案:

What could they be doing that would cause fork() to crash like this?

我发现这个 [错误] bug report 针对 glibc 提交,其中 OP [或多或少] 写道:

I called sigaction() with a mostly un-initialized struct instance when setting up a handler for SIGCHLD. Later, when I call fork() and the SIGCHLD handler executes, my program crashes.

我设法证明他们确实在他们的代码中至少在一处做到了这一点。为了测试这是否是罪魁祸首,我在调用有问题的函数之前 zero-initialized %ESP 下面的堆栈。不幸的是,它仍然在崩溃,尽管我认为很可能还有其他地方在做这种事情。

雪上加霜的是,除非我们支付额外费用,否则公司不愿意修复它。唉。