Я столкнулся со следующей проблемой в последней версии OS X 10.8.2, с последней версией Xcode 4.5.
Возьмите следующий простой фрагмент кода:
#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 foo
или же g++ foo.cpp -o foo
и запустить его с помощью ./foo
требуется много времени для запуска, как и ожидалось.
Теперь сделайте либо lldb ./foo
или же gdb ./foo
, затем run
и обратите внимание, что это завершается за 3 секунды. Каждый раз, когда используется какой-либо отладчик, первый оператор сна, по-видимому, игнорируется.
Поскольку Xcode по умолчанию использует lldb при запуске проекта, вставка приведенного выше кода в пустой проект Xcode и выполнение Product-> Run будут иметь аналогичные результаты.
Я попробовал тот же эксперимент на машине Linux с GDB 7.2, и проблема делает не происходят там.
Это ошибка в более старой версии GDB, которую использует Apple (GDB 6.3.50-20050815 (версия Apple GDB-1822)), или это что-то еще? Возможно только мой компьютер испорчен, если это не случается с другими пользователями OS X?
хотя многие люди не используют его, 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.
Конечно, ожидаемое значение возвращается с учетом наблюдаемого поведения.
Я думаю, что проблема связана с тем фактом, что всякий раз, когда отладчик хочет приостановить процесс, если этот процесс находится в середине системного вызова (он выполняет код в стране ядра), этот системный вызов прерывается в стиле EINTR на Mac OS X. Я не знаю, как системы Linux справляются с этим, но именно это происходит в Mac OS X. Если вы запустите свою программу и в отдельном окне присоединитесь к ней с помощью lldb и продолжите процесс, вы обнаружите, что ваш сон (100000); вызов прекращается, как только выполнение возобновляется. Похоже, что при выходе дочернего процесса должен передаваться сигнал SIGCHLD, и это вызывает прерывание родительского процесса отладчиком — но я не совсем понимаю, что приводит к тому, что длинный вызов sleep () завершается досрочно. в этом конкретном случае.