2012-09-26 47 views
1

我在最新版本的OS X 10.8.2上遇到了以下問題,並帶有最新的Xcode 4.5。lldb/gdb有什麼問題,忽略OS X中的第一個sleep()語句?

採取以下簡單的代碼:

#include <iostream> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <unistd.h> 

int main(int argc, const char * argv[]) 
{ 
    pid_t pid = fork(); 

    if (0 == pid) 
    { 
     std::cout << "Child process!\n"; 

     exit(0); 
    } 
    else if (-1 == pid) 
    { 
     std::cout << "Error forking.\n"; 
    } 
    else 
    { 
     std::cout << "In parent, created pid " << pid << ".\n"; 

     sleep(100000);  // Sleep a long time - GDB/LLDB ignores the first sleep statement 
     sleep(3);   // Sleep 3 more seconds - GDB/LLDB doesn't ignore the second sleep statement 

     std::cout << "Done in parent!\n"; 
    } 

    return 0; 
} 

編譯它使用clang++ foo.cpp -o foog++ foo.cpp -o foo並使用./foo運行它,這需要很長的時間來運行,如所預期。

現在做lldb ./foogdb ./foo,然後run並注意它在3秒內完成。無論何時使用調試器,第一個睡眠語句似乎都被忽略。

由於Xcode的默認運行項目時,粘貼上面的代碼到一個空白的Xcode項目和做產品展示 - >運行將有類似的結果使用LLDB。

我試過在gdb 7.2的Linux機器上進行同樣的實驗,問題是不是發生在那裏。

這是在舊版本的GDB的錯誤,蘋果應用程序(GDB 6.3.50-20050815(蘋果版GDB-1822)),或者是別的什麼?也許只是我的電腦搞砸了,如果它不發生在其他OS X用戶?

+1

它絕對不只是你。我將這個逐字記錄剪切/粘貼到我的Xcode中,解僱了它,並得到了完全相同的結果。夥計,這是起飛。我一直盯着你的代碼尋找一個bug,但我只是沒有看到任何。 – WhozCraig

+0

你是否將gdb設置爲跟隨孩子或父母,或者兩者都不是,或者兩者都不是,gdb會跟隨直接完成的父母。 –

+0

除了我在問題中提到的內容外,我沒有做任何事情。父母不應該馬上結束,因爲它有兩個睡在那裏。 –

回答

2

雖然很多人不使用它,sleep實際上有一個返回值。

man 3 sleep

返回值

If the sleep() function returns because the requested time has elapsed, 
the value returned will be zero. If the sleep() function returns due 
to the delivery of a signal, the value returned will be the unslept amount 
(the requested time minus the time actually slept) in seconds. 

果然,預期值返回考慮觀察到的行爲。

+0

你是對的,謝謝! 因此,當由lldb/gdb調試時,子進程退出導致信號發送到父進程。 然後我的問題是,什麼信號正在發送,爲什麼會發生在OS X的gdb 6.3.50,但不是在具有gdb 7.2的Linux系統上? –

+0

@DmitriShuralyov這兩個內核有很多不同之處;我不會猜測。相反...您可能想嘗試安裝信號處理程序,然後在沒有調試程序的情況下運行(因爲調試程序可能截取信號)。 – justin

+0

你知道是否有辦法安裝攔截所有信號的信號處理程序?或者我必須單獨設置每個信號處理程序,並希望提及所有信號處理程序(以便捕獲正在發送的信號處理程序)? –

1

我認爲這個問題是由於調試器需要的任何時間暫停過程中,如果這個過程是在一個系統調用(這是執行在內核土地碼)的中間,即系統調用在Mac OS X上放棄了EINTR風格。我不知道Linux系統如何處理這個問題,但這就是Mac OS X上發生的事情。如果你運行你的程序,並在一個單獨的窗口中用lldb附加它並繼續這個過程,你會發現你的睡眠(100000);呼叫在執行恢復後立即終止。當子進程退出並且導致父進程被調試器中斷時,似乎必須有一個SIGCHLD信號被廣播 - 但我並不完全清楚什麼導致了長時間sleep()調用被提前結束在這個特定的情況下。