我编写了一个多线程程序,该线程的实现方式是分叉子进程,并通过这个子进程加载了几个模块。
在我一次测试期间,我发现进程(在solaris平台上运行)中止了一次,并且它产生了一个分段错误。在浏览转储文件时,我非常震惊地看到solaris中的fork()系统调用导致了这种分段错误。
下面是fork()abort时的堆栈跟踪:
(l@5) stopped in (unknown) at 0xfe524970
0xfe524970: <bad address 0xfe524970>
(/opt/SUNWspro/bin/../WS6U2/bin/sparcv9/dbx) where
[1] 0xfe524970(0xfe524970, 0x0, 0xffffffff, 0x1, 0x0, 0x0), at 0xfe52496f
[2] run_prefork(0xfecc04b8, 0xfecc04d0, 0x242f4, 0xfea5d3c8, 0x0, 0x0), at 0xfec97ce8
[3] _ti_fork1(0x1, 0x1ab18, 0x0, 0x0, 0x0, 0x0), at 0xfea5d3c8
[4] _ti_fork(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0xfea5d50c
有人能描述为什么solaris中的fork()系统调用会导致这种行为吗?
答案 0 :(得分:1)
增加:
可能的情况可能是(让我们以C ++为例):
fork()
fork()
fork()
根据时间安排,这或多或少可能发生。也许你可以通过引入一些睡眠来强制执行这种情况......(如果你觉得这可能就是这种情况)
另一个问题可能是某些硬件缺陷。我会让一个工具检查RAM运行,看看是否有问题,然后再进一步查看。如果是这种情况,请告诉我们。
另一种可能性是系统代码中的一个错误,它无法解释为什么有时它不起作用。对我来说,问题似乎不太可能。
PS地址at 0xfe52496f
是奇数/不是四的倍数,这对于优化程序来说并不常见。这也暗示了缺陷RAM的方向......我希望我错了,另一方面,如果我是对的,你知道该怎么做......
答案 1 :(得分:1)
混合叉子和线程通常是不明智的。这是因为分叉进程只有一个线程,即调用fork的线程。新进程中不存在所有其他线程,这意味着任何共享内存资源都处于未知状态。另一个线程可以持有互斥锁,但永远不会释放它等。有一些机制可以缓解这种情况,例如pthread_atfork
,但作为一般规则,你应该只在工作时尽快调用exec
有多个线程。您是在父进程或新子进程中进行分类吗?
答案 2 :(得分:0)
我认为您的堆栈或堆栈指针可能在您调用fork时已损坏。在您调用fork()
之前,或者您已经实际用完了堆栈空间并且堆栈指针只是处于该限制之下。
调用其他函数或在调用alloca
之前将memset
和fork
该区域分配给适当的内存为0将显示是否属于这种情况,因为错误会提前出现。
如果你在一个进程的非主线程中分叉(我不熟悉Solaris的线程模型,所以我可能会大肆吹嘘)你也可能会以某种方式指定/分配这个线程(一个调用fork
)堆栈的方式,以防止在fork之后新进程可以访问它。
这是可重复的吗?它是否一直发生?