2010-06-04 51 views
1

我已經寫了一個多線程程序,並且以這樣的方式實現了線程,以便分叉子進程並通過此子進程加載幾個模塊。fork系統調用導致分段錯誤

在我一次測試過程中,我發現進程(在solaris平臺上運行)中止一次,並且它創建了segementation錯誤。在通過轉儲文件時,我真的很震驚地發現solaris中的fork()系統調用導致了這種分段錯誤。

下面是在叉時的堆棧跟蹤()中止:

([email protected]) 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()系統調用導致這種行爲?

+1

你確定SIGSEGV發生在你打印堆棧的線程中,而不是其他的?你提到你的應用是多線程的。 – bobah 2010-06-04 07:08:58

+1

可否請您在這裏顯示一些代碼以獲得清晰的圖片 – Vijay 2010-06-04 07:32:34

+0

不可能從您的信息中判斷。可能是任何事情。請發佈您的源代碼片段,用於創建線程和清理線程。許多事情可能在這些階段出錯。 – Thorsten79 2010-06-04 07:54:25

回答

1

增加:

一個可能的方案可能是(讓我們C++爲例):

  • 創建在線程的對象的
  • 線程B調用調用fork()
  • 的方法
  • 線程A在線程B仍在運行之前刪除對象fork()
  • 然後,在實際期間內存地址無效致電fork()

根據時間,這可能會發生或多或少。也許你可以通過引入一些睡眠來強制這種情況...(如果你覺得可能是這種情況)

另一個問題可能是一些硬件缺陷。我會讓一個工具來檢查內存運行,看看有沒有問題,然後再看看。讓我們知道是否是這種情況。

另一種可能性是系統代碼中的錯誤,它不能解釋爲什麼有時它有時不起作用。對我來說,這不太可能是問題所在。

PS地址at 0xfe52496f是奇數/不是四的倍數,這對優化程序來說並不常見。這也是一個缺陷RAM的方向提示...我希望我錯了,另一方面,如果我是對的,你知道該怎麼辦...

+0

您可以詳細說明for()系統調用中硬件缺陷如何導致分段錯誤嗎? – Santhosh 2010-06-04 08:56:46

+0

我不確定明白你的意思。你問我是否它是一個內存缺陷,爲什麼它特別在調用fork()時出現。也許是因爲lib總是映射在同一個物理地址周圍?與此同時,我還有另一種可能對您有所幫助的場景(請再次參閱答案文本) – jdehaan 2010-06-04 10:04:01

0

我認爲你的堆棧或堆棧指針可能有在您撥打fork的位置已損壞。無論是或者你已經用完了你的堆棧空間,並且在你撥打fork()之前,堆棧指針只是在這個限制之內。

調用等功能,或只是調用fork之前allocamemset該區域爲0分配的內存中等量如果是這種情況下,誤差會較早出現本身就揭示。

如果你在進程的非主線程中分叉(我不熟悉Solaris的線程模型,所以我可能會吹笛子),你可能會以某種方式指定/分配該線程的(一個叫fork)以這樣一種方式堆疊,以防止它在叉子之後被新過程訪問。

這是可重複的嗎?它是否一致發生?

1

混合叉和螺紋通常是不明智的。這是因爲分叉進程只會有一個線程,即稱爲fork的線程。所有其他線程都不存在於新進程中,這意味着任何共享內存資源都處於未知狀態。另一個線程可以容納一個互斥鎖並且永遠不會釋放它等等。有一些機制可以緩解這種情況,例如pthread_atfork,但是作爲一般規則,您應該只在使用多個線程時儘快致電exec。您是否在父流程或新流程中進行了細分?