Reputation: 1090
I have this small program:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
int orig = 1;
for (int i = 0; (i != 3) && orig; ++i) {
orig = orig && fork();
}
if (orig) {
for (int i = 0; i != 3; ++i) {
wait(NULL);
}
} else {
int num;
scanf("%8d", &num);
printf("%d\n", num*num);
}
}
Which is supposed to simply square three numbers that it reads from stdin
. And if I type the numbers in myself, it works:
akiiino$ ./out.out
12345678
12345678
12345678
260846532
260846532
260846532
but if I use cat for the same purpose, it does not work as expected:
akiiino$ cat in.txt
12345678
12345678
12345678
akiiino$ cat in.txt | ./out.out
260846532
0
0
What is the reason behind this weird behavior and is it fixable? I've always assumed cat
ing files was no different from typing them into stdin
.
Upvotes: 2
Views: 123
Reputation: 148880
The difference is that when you type the 3 numbers by hand, you are reading from a terminal and low level reads are terminated on newlines. Let's look what happens under the hood.
manual input:
read
call is terminated by the newline because you read from a terminalscanf
call decode the input an does its processingOk, we iterate the same for the 2 other childs
reading from a file or a pipe
read
of first child reads and consumes all the input in the stdio bufferscanf
call decode the (first part of the) input an does its processingBut now the 2 other childs are reading from a file/pipe positioned at end of file. Their scanf returns 0 but you fail to control it, and they let the initial undeterminated value in num
.
You can control that it is not a problem of race condition by adding a sleep(10)
before the loop, starting the program an inputting by hand 3 numbers before first child begins to read. As the low level reads will be newline terminated (special tty case) you still get same output of the first case, even if the 3 lines are available before the first read.
Upvotes: 3
Reputation: 135
Already said by @Some programmer dude, problem is with the fork
command.
If you try ./out.out < in.txt
, it should work fine.
Upvotes: 0