Time & Clocks · Section 2
nanosleep(2)
Suspend the calling thread for the specified duration with nanosecond precision.
Signature
#include <time.h>
int nanosleep(const struct timespec * req, struct timespec * rem);- req
- Requested sleep duration. tv_sec is seconds, tv_nsec is the fractional nanoseconds in [0, 999_999_999].
- rem
- If non-NULL and the call is interrupted, receives the remaining unslept time. Pass NULL when restart-on-EINTR is not needed.
Description
nanosleep() suspends the calling thread for at least the time specified in *req — a struct timespec with seconds and nanoseconds. It uses CLOCK_MONOTONIC, so it's unaffected by wall-clock adjustments (NTP, settimeofday). If interrupted by a signal whose handler does not specify SA_RESTART, the call returns -1/EINTR and writes the remaining unslept time to *rem (if non-NULL) — the caller can retry with rem to complete the original duration. Returns 0 on full completion. The kernel rounds up to the granularity of the system clock; high-resolution-timer kernels honour requests down to ~1 µs. For absolute-time sleeps or for waking on CLOCK_REALTIME with timezone semantics, use clock_nanosleep() — it takes an explicit clock id and a TIMER_ABSTIME flag.
Architecture mapping
| Architecture | Number | ABI | Entry point |
|---|---|---|---|
| x86 (i386) | 162 | i386 | sys_nanosleep_time32 |
| x64 (x86_64) | 35 | common | sys_nanosleep |
| ARM64 (aarch64) | 101 | — | — |
Kernel history
Introduced in Linux 2.0.
2.0
nanosleep() was added in 2.0 as the high-resolution replacement for the second-granularity sleep().
2.6.21
clock_nanosleep() was added so applications can sleep against a specific clock (CLOCK_MONOTONIC, CLOCK_REALTIME, CLOCK_BOOTTIME), and with TIMER_ABSTIME for sleeping until a wall-clock instant — eliminating accumulating drift from request → sleep → continue loops.
seccomp & containers
Docker default profile
Allowed
Podman default profile
Allowed
nanosleep() and clock_nanosleep() are on every default profile. Blocking them would break essentially every program — sleep is too fundamental. No useful argument-level filtering.
libseccomp
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(nanosleep), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clock_nanosleep), 0);strace example
$ strace -e nanosleep sleep 0.05
nanosleep({tv_sec=0, tv_nsec=50000000}, NULL) = 0nanosleep() in strace shows the struct timespec decoded. -r adds relative-time annotations so you can see whether the actual elapsed time matches the request. Programs that exhibit unexplained latency often have an accidental nanosleep() in a hot loop — strace -c surfaces it as 100%+ time in nanosleep().
Security & observability
nanosleep() is rarely a defender's signal but worth knowing for two patterns: (1) Sandbox-evasion malware sleeps for minutes/hours at startup to outlast automated dynamic-analysis sandboxes — a long nanosleep() at process start is a classic red flag for behavioural classifiers. (2) Timing-based brute-force and side-channel attacks calibrate themselves with nanosleep() between probes. eBPF tracepoint sys_enter_nanosleep with a long tv_sec is a low-cost telemetry feed. For benign workloads, nanosleep() is just noise.
Errors
- EFAULT
- req or rem pointer is invalid.
- EINTR
- Interrupted by a signal. *rem holds the unfinished portion; loop on EINTR for full duration.
- EINVAL
- tv_nsec is out of range, or tv_sec is negative.