time_nanosleep

Delays execution for a given number of seconds and nanoseconds, reporting time left if interrupted.

Signature
time_nanosleep(int $seconds, int $nanoseconds): array|bool
  • Added in PHP 5.0

Parameters

ParameterTypeDescription
$secondsintWhole seconds to wait. Must not be negative.
$nanosecondsintAdditional nanoseconds to wait. Must be non-negative and less than 1,000,000,000.

Return value

array|booltrue on success, false on failure. If a signal interrupted the delay, an array with the keys seconds and nanoseconds holding the remaining time is returned instead.

Errors

Passing a negative seconds value, or a nanoseconds value that is negative or 1,000,000,000 or greater, is rejected as an invalid argument.

time_nanosleep() is the precise cousin of sleep(). You give it a whole-second part and a nanosecond part, and unlike sleep() or usleep() it tells you how much of the delay was left if a signal cut it short.

When to reach for it

  • Pacing a loop to a target rate where microsecond drift matters, such as an audio or sensor sampling script.
  • Any CLI script that installs signal handlers with pcntl and must resume a partially completed wait.
  • Delays expressed naturally in nanoseconds alongside hrtime() measurements.

What trips people up

The return type is the trap. Success is true, failure is false, but an interrupted call returns an array — which is truthy. Writing if (time_nanosleep(1, 0)) { /* slept fully */ } treats an interruption as success. Compare with === true, or check is_array() and sleep the remainder.

Also note that the nanosecond argument must stay below one billion; roll whole seconds into the first argument rather than passing 1_500_000_000. Actual resolution depends on the OS scheduler, so on Windows especially the real pause can be noticeably longer than requested.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Throttling a polling loop to a precise interval such as 250 ms per iteration.
  • Resuming the remaining wait after a SIGALRM or SIGINT interrupts a long delay in a daemon.
  • Spacing out writes to a rate-limited device or serial port in a CLI tool.

Frequently asked questions

What is the difference between time_nanosleep and usleep?

usleep() takes microseconds and returns nothing useful, while time_nanosleep() takes a seconds plus nanoseconds pair and reports the remaining time when a signal interrupts the delay.

Why does my check on the return value always pass?

An interrupted call returns an array, and arrays are truthy. Use $result === true to test for a fully completed delay.

Can I pass more than one billion nanoseconds?

No. The nanoseconds argument must be less than 1,000,000,000; put whole seconds in the first argument instead.

More examples

Handling an interrupted delay correctly

Without a signal the loop body never runs and only "done" prints, but the pattern shown is what correctly finishes the remaining delay when a signal does interrupt it.

Example · php
<?php
function waitFully(int $sec, int $nsec): void {
    $result = time_nanosleep($sec, $nsec);

    while (is_array($result)) {
        echo "interrupted, {$result['nanoseconds']}ns left\n";
        $result = time_nanosleep($result['seconds'], $result['nanoseconds']);
    }
}

waitFully(0, 100_000_000);
echo "done\n";

Pacing a loop to a fixed interval

The three ticks land near 100, 200 and 300 milliseconds, showing the delay accumulating at roughly the requested rate with a small scheduler overshoot each time.

Example · php
<?php
$interval = 100_000_000;
$start = hrtime(true);

for ($i = 1; $i <= 3; $i++) {
    time_nanosleep(0, $interval);
    $ms = (hrtime(true) - $start) / 1_000_000;
    printf("tick %d at %.0f ms\n", $i, $ms);
}

Discussion

  • Be the first to comment on this lesson.