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

int main(){
    char buf[10];

    pid_t pid = fork();

    if (pid < 0){
        printf("error fork\n");
        exit(1);
    }
    if (pid == 0){
        fgets(buf,5,stdin);
        printf("Child : %s\n",buf);
        
    }
    else{
        wait(NULL);
        char* r = fgets(buf,5,stdin);
        if (r == NULL){
            printf("Parent : eof = %i\n",feof(stdin));
        }
        else {
            printf("Parent : %s\n",buf);
        }
        
    }
    return 0;
}

My program is very simple : a process is forked; the child process reads 4 characters from stdin and when it finishes, the parent process reads 4 characters from stdin.

Normally, if I write characters in stdin (before the fork) the child process should read the first 4 characters and then the parent process should read the next 4 characters. It seems quit logical as fork() duplicates the parent process, including the file descriptors and opened files.

But, when I execute echo 'aaaaaaaaa' | ./my_program I get Child : aaaa Parent : eof = 1

It seems that stdin has been emptied by the child process when it finished. I having hard time explaining this behavior.

Can you help me ? :)

ax_fer
  • 13
  • 2

2 Answers2

1

Standard input is usually (Is stdout line buffered, unbuffered or indeterminate by default?) line buffered by default. Check this answer to see what exactly this entails.

If you want your program to work as expected, explicitly set your standard input to be unbuffered (before the fork() call). This can be done like so:

setbuf(stdin, NULL);

Also see Should I set stdout and stdin to be unbuffered in C? for more implications of setting stdin to be unbuffered.

Janez Kuhar
  • 3,705
  • 4
  • 22
  • 45
-3

Try comment out after "else{"

//wait(NULL);
  • 1
    Removing the wait from the parent would not change the fact that the stream is buffered, so whichever process performs its `fgets` first is likely to get the entire line as it fills its buffer, starving the other process of input. – Eric Postpischil Nov 05 '22 at 10:24
  • But at me with commented "wait(NULL)" parent prints "aaaaa". – Peter Irich Nov 05 '22 at 11:29
  • @PeterIrich That's true. But then the child doesn't print anything. – Janez Kuhar Nov 05 '22 at 11:36
  • There is my output when "wait(NULL)" is commented: peter@peter1955:~/Documents> echo "aaaaaaa" | ./zzz_fork.elf Parent : aaaa Child : – Peter Irich Nov 05 '22 at 12:11
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Nov 08 '22 at 16:11