为什么不睡觉?

时间:2012-09-02 21:26:04

标签: objective-c macos cocoa unix system-calls

我有一个在单独的队列/线程上运行的函数。在这个函数中,我试图调用usleep

无论传入的值如何,usleep似乎都不起作用。 sleep()也是如此。

为了诊断错误,我打印出errnoerrno打印为:“系统调用中断”

这究竟是什么意思,我该如何进行诊断呢?

手册页将错误描述为:

[EINTR]            A signal was delivered to the process and its action was to invoke a signal-catching
                    function.

注意我在OSX Mountain Lion上使用Xcode 4并使用Objective-C。我正在使用Cocoa为OSX开发一个应用程序。

2 个答案:

答案 0 :(得分:4)

usleepsleep可以通过传递信号以这种方式中断。

没有专用的信号传递线程,因此可以将信号传递到应用程序中的任意线程。

注意下面留下的原始答案在Mountain Lion上正常工作 - 在XCode下运行时会触发EINTR。

为了避免这个问题,我们交换到nanosleep,并使用当它被中断时返回第二个参数中剩余时间的事实:

struct timespec to_sleep = { 1, 0 }; // Sleep for 1 second
while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));

虽然,如果您使用的是NSThread,那么最好使用:

[NSThread sleepForTimeInterval:1.0f]; // sleep for 1 second

这是可可的睡眠方式,并没有受到sleepusleepnanosleep经历的“打嗝”的影响

旧答案 - 在调试器下无法正常工作。

如果要阻止使usleep的线程被中断,则需要屏蔽可能传递给线程的所有信号。 e.g。

#include <signal.h>

sigset_t sigset;
sigset_t oldset;
sigfillset(&sigset);
pthread_sigmask(SIG_BLOCK, &sigset, &oldset);
usleep(9999);
pthread_sigmask(SIG_SETMASK, &oldset, NULL);

注意:此代码中未完成错误检查

答案 1 :(得分:0)

您无法随时随意打印errno并希望它有用。它是一个每线程变量,只有在特定的系统调用设置它之后才能设置它。

即。您只能在确定呼叫失败后才能查看errno

两种呼叫都不太可能失败。极不可能。


从您的问题中不清楚您是否抓住了返回值。

  • 在调试器外部尝试,它可能是调试器输入信号的东西。如果是这样,那可能就是一个错误。

  • 您是否还有其他信号繁重的代码或子系统?一般来说,信号处理程序在Unix系统上很棘手。

  • 你在使用lldb吗?你尝试过切换到gdb吗?