2

I am running into the following problem on the latest version of OS X 10.8.2, with latest Xcode 4.5.

Take the following simple piece of code:

#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;
}

Compile it using clang++ foo.cpp -o foo or g++ foo.cpp -o foo and run it using ./foo, it takes a long time to run, as expected.

Now do either lldb ./foo or gdb ./foo, then run and notice it completes in 3 seconds. Whenever either debugger is used, the first sleep statement is seemingly ignored.

Since Xcode uses lldb by default when running a project, pasting the above code into a blank Xcode project and doing Product->Run will have similar results.

I've tried the same experiment on a Linux machine with gdb 7.2, and the problem does not occur there.

Is this a bug in an older version of gdb that Apple uses (gdb 6.3.50-20050815 (Apple version gdb-1822) ), or is it something else? Perhaps just my computer is messed up, if it doesn't happen to other OS X users?

4

2 回答 2

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.

果然,考虑到观察到的行为,返回了预期值。

于 2012-09-26T05:08:06.157 回答
1

我认为问题是由于调试器想要暂停进程的任何时候,如果该进程处于系统调用的中间(它正在内核领域执行代码),那么该系统调用就会中止 EINTR 样式Mac OS X。我不知道 Linux 系统是如何处理这个问题的,但这就是在 Mac OS X 上发生的事情。如果你运行你的程序,并在一个单独的窗口中用 lldb 附加到它并继续这个过程,你会发现你的睡眠(100000);一旦执行恢复,调用就会终止。似乎当子进程退出时必须广播 SIGCHLD 信号,这导致父进程被调试器中断 - 但我并不完全清楚导致长 sleep() 调用提前结束的原因在这种特定情况下。

于 2012-09-27T21:48:56.100 回答