Skip to content
/linux-syscalls

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

ArchitectureNumberABIEntry point
x86 (i386)162i386sys_nanosleep_time32
x64 (x86_64)35commonsys_nanosleep
ARM64 (aarch64)101

Kernel history

Introduced in Linux 2.0.

  1. 2.0

    nanosleep() was added in 2.0 as the high-resolution replacement for the second-granularity sleep().

  2. 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) = 0

nanosleep() 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.

Related syscalls