I have a function that is being run on a separate queue/thread. In this function I am trying to call usleep
.
Regardless of the value passed in, usleep
doesn't seem to work. The same goes for sleep()
.
To diagnose the error, I printed out errno
. errno
prints as: "Interrupted system call"
What exactly does this mean, and how could I go about diagnosing it?
The man pages describe the error as:
[EINTR] A signal was delivered to the process and its action was to invoke a signal-catching
function.
Note I am on OSX Mountain Lion using Xcode 4 and using Objective-C. I am developing an app for OSX using Cocoa.
usleep
and sleep
can be interrupted in this manner by the delivery of signals.
There is no dedicated signal delivery thread, so signals can be delivered to arbitrary threads in your application.
Note Original answer left below does not work properly on Mountain Lion - something else is triggering the EINTR when run under XCode.
To avoid this problem, we swap over to nanosleep
, and use the fact that when it gets interrupted it returns the remaining time in the second parameter:
struct timespec to_sleep = { 1, 0 }; // Sleep for 1 second
while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
Although, if you're using an NSThread, then you're better off using:
[NSThread sleepForTimeInterval:1.0f]; // sleep for 1 second
which is the Cocoa way of sleeping, and does not suffer from the 'hiccuping' that sleep
, usleep
and nanosleep
experience
Old Answer - Does not work properly under the debugger.
If you want to prevent the thread that has your usleep
from being interrupted, you need to mask out all the signals that may be delivered to the thread. 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);
Note: No error checking done in this code
You can't arbitrarily print errno
at any time and expect it to be useful. It is a per-thread variable that will only be set after a particular syscall sets it.
I.e. you can only check errno
when you have determined that a call has failed.
It is highly unlikely that either call is failing. Exceedingly unlikely.
It wasn't clear from your question that you were grabbing the return value.
Try it outside the debugger, it may be the debugger hosing things w/signals. If so, it is likely a bug.
Do you have any other signal heavy code or subsystems in play? Signal handlers are screwy on Unix systems, in general.
are you using lldb? have you tried switching to gdb?