Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sleep function in C (POSIX) breaks my program

Tags:

c

fork

posix

sleep

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.

like image 932
Alberto Perugini Avatar asked Feb 25 '26 12:02

Alberto Perugini


2 Answers

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)

like image 85
klutt Avatar answered Feb 27 '26 00:02

klutt


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.

like image 25
Basile Starynkevitch Avatar answered Feb 27 '26 01:02

Basile Starynkevitch



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!