1

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.

fdh
  • 5,256
  • 13
  • 58
  • 101

2 Answers2

4

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

Anya Shenanigans
  • 91,618
  • 3
  • 107
  • 122
  • That might work (but I doubt it if it is the debugger), but it doesn't really answer OP's question. The real issue is *why doesn't it work in the first place*? It should work. – bbum Sep 03 '12 at 19:05
  • Huh, there appears to be 4 interrupts when running under the debugger. Even with the signal blocking code, it just doesn't work. I'll refactor the answer to use the nanosleep trick. – Anya Shenanigans Sep 04 '12 at 09:41
0

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?

bbum
  • 162,346
  • 23
  • 271
  • 359
  • I am aware of that. However in this case, the call *did* fail. At failure, usleep() returns -1. I checked the returned value; its -1. – fdh Sep 03 '12 at 02:15
  • You question, as worded, doesn't indicate that. Fair enough. – bbum Sep 03 '12 at 03:51
  • I tried it outside the debugger but I still get an identical error. I do not have any signal heavy code and I am using gdb. – fdh Sep 03 '12 at 20:23
  • OK -- try `usleep()` in `main()` prior to doing anything. Then try it in a standalone program. Something *very odd* is going on with signals in your app. – bbum Sep 04 '12 at 01:23