Alberto Perugini
Alberto Perugini

Reputation: 35

Sleep function in C (POSIX) breaks my program

This is my program code:

#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <sys/types.h>

void function() {
    srand(time(NULL));
    while(1) {
        int n = rand();
        printf("%d ", n);
        //sleep(1);
    }
}

int main() {
    pid_t pid;

    pid = fork();
    if (pid == 0) {
        function();
    }
}

With the sleep line commented out (as in the code above) the program works fine (i.e. it prints a bunch of random numbers too fast to even see if they are actually random), but if I remove the comment the program doesn't print anything and exits (not even the first time, before it gets to the sleep), even though it compiles without warnings or errors with or without the comment.

Upvotes: 3

Views: 355

Answers (2)

I believe you need to call fflush(3) from time to time. See also setvbuf(3) and stdio(3) and sysconf(3).

I guess that if you coded:

while(1) {
    int n = rand();
    printf("%d ", n);
    if (n % 4 == 0)
       fflush(NULL);
    sleep(1);
}

The behavior of your program might be more user friendly. The buffer of stdout might have several dozens of kilobytes at least.

BTW, I could be wrong. Check by reading a recent C draft standard (perhaps n2176).

At the very least, see this C reference website then syscalls(2), fork(2) and sleep(3).

You need to call waitpid(2) or a similar function for every successful fork(2).

If on Linux, read also Advanced Linux Programming and use both strace(1) and gdb(1) to understand the behavior of your program. With GCC don't forget to compile it as gcc -Wall -Wextra -g to get all warnings and debug info.

Consider also using the Clang static analyzer.

Upvotes: 1

klutt
klutt

Reputation: 31296

but if I remove the comment the program doesn't print anything and exits

It does not print, but it does not really exit either. It will still be running a process in the background. And that process runs your infinite while loop.

Using your code in p.c:

$ gcc p.c 

$ ./a.out 

$ ps -A | grep a.out
 267282 pts/0    00:00:00 a.out

$ killall a.out

$ killall a.out
a.out: no process found

The problem is that printf does not really print. It only sends data to the output buffer. In order to force the output buffer to be printed, invoke fflush(stdout)

If you're not flushing, then you just rely on the behavior of the terminal you're using. It's very common for terminals to flush when you write a newline character to the output stream. That's one reason why it's preferable to use printf("data\n") instead of printf("\ndata"). See this question for more info: https://softwareengineering.stackexchange.com/q/381711/283695

I'd suspect that if you just leave your program running, it will eventually print. It makes sense that it has a finite buffer and that it flushes when it gets full. But that's just an (educated) guess, and it depends on your terminal.

it prints a bunch of random numbers too fast to even see if they are actually random

How do you see if a sequence of numbers is random? (Playing the devils advocate)

Upvotes: 4

Related Questions