Second precision
Nanosecond precision
POSIX.1b
What Is Process Sleeping?
Sleeping suspends a process (or thread) for a fixed amount of time. The kernel puts the process in an unrunnable state and wakes it when the interval elapses โ or earlier if a signal arrives.
Linux provides two main sleep functions: the simple sleep() and the higher-precision nanosleep().
| Feature | sleep() | nanosleep() |
|---|---|---|
| Header | <unistd.h> |
<time.h> |
| Precision | Whole seconds only | Up to 1 nanosecond |
| Return on interrupt | Remaining seconds (unsigned int) | -1 + errno=EINTR + remaining in remain |
| Signal interactions | May interact with alarm() on some systems | Safe to mix with alarm() / setitimer() |
| Linux implementation | Calls nanosleep() internally | Direct syscall |
| Portability concern | Some systems use alarm() โ avoid mixing | POSIX.1b โ widely supported |
#include <unistd.h>
/* Sleep for 'seconds' seconds. Returns remaining seconds if
interrupted by a signal, or 0 on completion. */
unsigned int sleep(unsigned int seconds);
/* ----------------------------------------- */
#define _POSIX_C_SOURCE 199309
#include <time.h>
struct timespec {
time_t tv_sec; /* Seconds */
long tv_nsec; /* Nanoseconds 0..999999999 */
};
/* Sleep for interval specified in 'request'.
If interrupted, returns -1 with errno=EINTR,
and 'remain' (if non-NULL) holds the unslept time. */
int nanosleep(const struct timespec *request,
struct timespec *remain);
/* Returns 0 on completion, -1 on error/interrupt */
When a signal interrupts nanosleep(), restart it with the remaining time to complete the full sleep interval.
#include <stdio.h>
#include <unistd.h>
#include <time.h>
int main(void) {
time_t start, end;
printf("Sleeping for 3 seconds...\n");
start = time(NULL);
unsigned int remaining = sleep(3);
end = time(NULL);
if (remaining == 0) {
printf("Woke up normally. Elapsed: %ld seconds\n",
(long)(end - start));
} else {
printf("Sleep interrupted! %u seconds remaining.\n",
remaining);
}
/* sleep() on Linux does NOT interact with alarm() since
it calls nanosleep() internally โ safe to mix */
return 0;
}
/* Output: Sleeping for 3 seconds...
Woke up normally. Elapsed: 3 seconds */
#define _POSIX_C_SOURCE 199309
#include <stdio.h>
#include <time.h>
#include <errno.h>
int main(void) {
struct timespec req, rem;
/* Sleep for 250 milliseconds = 0 seconds + 250,000,000 ns */
req.tv_sec = 0;
req.tv_nsec = 250000000L; /* 250 ms */
printf("Sleeping for 250ms...\n");
if (nanosleep(&req, &rem) == 0) {
printf("Slept successfully.\n");
} else {
if (errno == EINTR) {
printf("Interrupted! Remaining: %ld.%09ld s\n",
rem.tv_sec, rem.tv_nsec);
}
}
/* Sleep for 1.5 seconds */
req.tv_sec = 1;
req.tv_nsec = 500000000L; /* 0.5 s */
printf("Sleeping for 1.5 seconds...\n");
nanosleep(&req, NULL);
printf("Done.\n");
return 0;
}
/* Output:
Sleeping for 250ms...
Slept successfully.
Sleeping for 1.5 seconds...
Done.
*/
Loop to ensure the full sleep interval completes even when interrupted by signals.
#define _POSIX_C_SOURCE 199309
#include <stdio.h>
#include <time.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
/* A signal handler that does nothing โ just interrupts nanosleep */
static void sigint_handler(int sig) {
printf("\n[Signal %d caught โ will restart sleep]\n", sig);
}
/**
* Sleep for 'secs' seconds + 'nsecs' nanoseconds.
* Automatically restarts if interrupted by signals.
* Returns: 0 on success, -1 on real error.
*/
int reliable_sleep(long secs, long nsecs) {
struct timespec req, rem;
req.tv_sec = secs;
req.tv_nsec = nsecs;
while (nanosleep(&req, &rem) == -1) {
if (errno == EINTR) {
/* Signal interrupted us โ resume with remaining time */
req = rem;
} else {
return -1; /* Real error */
}
}
return 0;
}
int main(void) {
struct sigaction sa;
/* Allow Ctrl-C (SIGINT) to interrupt but not kill */
sa.sa_handler = sigint_handler;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sigaction(SIGINT, &sa, NULL);
printf("Sleeping for 5 seconds. Press Ctrl-C to test interruption...\n");
if (reliable_sleep(5, 0) == 0) {
printf("Full 5-second sleep completed.\n");
}
return 0;
}
/* Even if you press Ctrl-C multiple times, the program
eventually completes the full 5-second sleep.
Sample run:
Sleeping for 5 seconds. Press Ctrl-C to test interruption...
[Signal 2 caught โ will restart sleep]
[Signal 2 caught โ will restart sleep]
Full 5-second sleep completed.
*/
nanosleep() accepts nanosecond values, but actual delivery is rounded up to the jiffy boundary (same as setitimer). High-res timers close this gap.
Each restart of nanosleep rounds up again. With very high signal rates, total sleep can drift. Use clock_nanosleep(TIMER_ABSTIME) to avoid this (covered in Part 6).
The number of remaining (unslept) seconds. If it completed normally, it returns 0.
Nanosecond precision, explicit remaining-time via the remain argument, and guaranteed independence from alarm()/setitimer() signals (POSIX says it must not use signals internally).
On some implementations, sleep() is implemented using alarm() and SIGALRM. Calling both can corrupt timer state. On Linux specifically it is safe (sleep calls nanosleep), but for portability avoid mixing.
Loop calling nanosleep() in a while loop. When it returns -1 with errno==EINTR, copy remain back to request and call again. Exit the loop when nanosleep() returns 0.
0 to 999,999,999 (inclusive). It represents nanoseconds within the current second. Values outside this range cause nanosleep() to fail with EINVAL.
