71GA
71GA

Reputation: 1391

clock_nanosleep(): It ignores timespec structure

I am trying to create this basic clock_nanosleep example but it will not pause my for loop which keeps on printing numbers. If I uncomment the //t.tv_nsec = s/1000000000; nothing will be printed, but for loop will be running.

// POSIX.1-2017 is what compiler is confined to.
#define _XOPEN_SOURCE 700

// C headers.
#include <stdint.h>
#include <time.h>
#include <stdio.h>
   
int main(int argc, char *argv[])
{
    // Counter.
    uint8_t i;

    // Time.
    int s = 1;

    // Create a timespec structure and calculate it's members.
    struct timespec t;
    t.tv_sec = s;
    //t.tv_nsec = s/1000000000;

    // Set flags i.e. TIMER_ABSTIME to 0 to use relative instead of absolute time.
    int flags = 0;

    // Choose the clock i.e. CLOCK_MONOTONIC is a "clock_id" for the clock started at system start.
    int clock_id = CLOCK_MONOTONIC;

    for(i = 0; i < 256; i++){
        printf("%d", i);

        // Because last argument is NULL in case of error, remaining time is not stored in "t".
        clock_nanosleep(clock_id, flags, &t, NULL);
    }

    return 0;

}

I have absolutely no clue why this isn't working. POSIX states that:

int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, struct timespec *rmtp);

If the flag TIMER_ABSTIME is not set in the flags argument, the clock_nanosleep() function shall cause the current thread to be suspended from execution until either the time interval specified by the rqtp argument has elapsed, or a signal is delivered to the calling thread and its action is to invoke a signal-catching function, or the process is terminated.

I made sure flag is zeroed out. And I set the rqtp i.e. &t.

The clock used to measure the time shall be the clock specified by clock_id.

I did use the CLOCK_MONOTONIC.

If the clock_nanosleep() function returns because it has been interrupted by a signal, it shall return the corresponding error value. For the relative clock_nanosleep() function, if the rmtp argument is non NULL, the timespec structure referenced by it shall be updated to contain the amount of time remaining in the interval (the requested time minus the time actually slept). The rqtp and rmtp arguments can point to the same object. If the rmtp argument is NULL, the remaining time is not returned. The absolute clock_nanosleep() function has no effect on the structure referenced by rmtp.

I also set last argument to NULL in order not to store the remaining time if clock_naanosleep() is interrupted by any signal.

So why this doesn't work?

Upvotes: 0

Views: 422

Answers (2)

dbush
dbush

Reputation: 224167

Local variables are not implicitly initialized. So if you don't set t.tv_nsec it could contain any value. If that value happens to be outside the range of 0 - 999999999 then clock_nanosleep will return immediately with an error code.

The reason you don't see any output when you do set t.tv_nsec is because of how you're printing:

 printf("%d", i);

You're not including a newline in the output. The stdout stream is line buffered, so it won't automatically flush the output stream to the console. Add \n to the end of the format string and you'll see the lines print.

Upvotes: 2

koder
koder

Reputation: 2093

In case like this you should always check what the actual return value is, which in this case will be EINVAL as the t.tv.nsec was not initialized.

Use:

struct timespec t = {
    .tv_sec = s,
};

To properly initialize all of the fields, even the ones you do not intend to use.

Upvotes: 2

Related Questions