1
static void timeDelay(int no_of_seconds)
{
#ifdef _WIN32
    Sleep(1000 * no_of_seconds);
#else
    sleep(no_of_seconds);
#endif
}

void somefunction(){
printf("\t\t Load ... \n\t\t"); 
fflush(stdout); 
for (int i = 1; i <= 60; i++)
        {
            fflush(stdout);
            timeDelay(1);
            if (i == 31)
                printf("\n\t\t");
            printf("*****");
        }
        
  }

I have included the header files too:

#ifdef _WIN32
    #include <windows.h>
#else
    #include <unistd.h>

The stars are printed instantaneously. I added fflush(stdout) after seeing the answers here. I also commented out the if (i==31) {} portion to check if that's causing the problem but it isn't. So what is wrong with my code?

mcleod_ideafix
  • 11,128
  • 2
  • 24
  • 32
Archer
  • 271
  • 5
  • 15

1 Answers1

0

According to the sleep() manpage...

NOTES On Linux, sleep() is implemented via nanosleep(2). See the nanosleep(2) man page for a discussion of the clock used.

So I have rewritten your program to use nanosleep. As you are working with WSL, I've dropped any reference to Win32, only Linux. Well, the thing is that this program exits nanosleep() prematurely, with an "Invalid argument" error. I cannot see why is that.

#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>

void timeDelay (time_t no_of_seconds)
{
  struct timespec req, rem;
  int res;

  req.tv_sec = no_of_seconds;
  req.tv_nsec = 0;

  do
  {
    rem.tv_sec = 0;
    rem.tv_nsec = 0;
    res = nanosleep (&req, &rem);
    req = rem;
  }
  while (res == EINTR);
  if (res)
    perror("nanosleep");
}

void somefunction()
{
  printf("\t\t Load ... \n\t\t");
  fflush(stdout);
  for (int i = 1; i <= 60; i++)
  {
    fflush(stdout);
    timeDelay(1);
    putchar('*');
  }
}

int main()
{
  somefunction();
  return 0;
}

I've also tried with NULL instead of rem, and reissuing nanosleep() with the original time instead of the remaining time, and putting the test and the perror() within the loop to print all possible errors from nanosleep. No matter what I do, I always receive an EINVAL from the first call to nanosleep()

So, there seems to be a real problema with nanosleep() on WSL. See https://github.com/microsoft/WSL/issues/4898 . It mentions a problem for WSL being unable to read the realtime clock from a certain version of glibc. I tried this in my WSL terminal:

$ sleep 1
sleep: cannot read realtime clock: Invalid argument

There is a mention of a workaround here: https://github.com/microsoft/WSL/issues/4898#issuecomment-612622828

I've tried with another approach: using clock_nanosleep() so I can choose another source for the clock: in the above program, just change the call to nanosleep() with this other to clock_nanosleep()

clock_nanosleep (CLOCK_MONOTONIC, 0, &req, &rem);

There is no problem with CLOCK_MONOTONIC, and now the program works!

mcleod_ideafix
  • 11,128
  • 2
  • 24
  • 32
  • I agree, this does not solve the issue. Nor does it really even address the question. How `sleep()` is implemented is irrelevant. That it behaves as it is documented to do (or that it didn't, if that were the case) is the point. And it *does* behave as documented for me on WSL. – John Bollinger Jun 28 '20 at 15:21
  • It IS relevant, as the underlying problem is that sleep() uses nanosleep(), and nanosleep() uses CLOCK_REALTIME which cannot be read in WSL. I've updated my answer anyway. – mcleod_ideafix Jun 28 '20 at 15:26
  • `sleep()` works as documented on WSL (for me). Perhaps it is buggy on some WSL providers, but that's a rather extraordinary claim. One of the key points of WSL is that it provides a fully functional Linux environment. Furthermore, if it does happen to be buggy on some WSL providers, that does not necessarily mean that the problem is with `nanosleep()`, though that is plausible. – John Bollinger Jun 28 '20 at 15:32
  • For some users it works fine. The issue is documented here also: https://discourse.ubuntu.com/t/ubuntu-20-04-and-wsl-1/15291 – mcleod_ideafix Jun 28 '20 at 15:38
  • Great. *That* would be the basis for an actual answer. "`sleep()` does not work correctly on some WSL providers, such as [...]". *Why* it doesn't work is a detail of little significance to the OP's question. – John Bollinger Jun 28 '20 at 16:06