Reputation: 67
This is what I'm trying to do: a parent process creates two child processes, then pipes stdout of one to stdin of another. Then parent waits for 5 secs and kills the first child.
This is how I approached it: First I create a pipe. Then fork to create the first child (gen in code) and dup2 to duplicate pipe's write onto stdout. Another fork for second child (called cons in code), dup2 to duplicate read end onto stdin. Cons just prints the data. Parent sends SIGTERM to first child, second child reads until EOF, so it closes on it's own.
Nothing but my error output (here used for debugging) is printed. Gen generates two random numbers, but loop in cons doesn't get executed. So I suppose there's nothing on stdin of cons. I consulted Google and followed this How do I chain stdout in one child process to stdin in another child in C?, but didn't manage to figure out what I messed up. Would appreciate any help. Thanks
Compilation: gcc -std=c99 -Wall -Werror main.c -o main
on Bash in Windows 10
Code:
#define _POSIX_SOURCE
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <signal.h>
#define READ_END 0
#define WRITE_END 1
#define BUF_SIZE 10
int main(int argc, char* argv[])
{
pid_t gen, cons;
int fd[2];
if (pipe(fd) < 0) {
// pipe error
exit(1);
}
gen = fork();
if (gen < 0) {
// fork error
close(fd[READ_END]);
close(fd[WRITE_END]);
exit(2);
} else if (gen == 0) {
// gen child
close(fd[READ_END]);
time_t t;
srand((unsigned)time(&t));
dup2(fd[WRITE_END], STDOUT_FILENO);
close(fd[WRITE_END]);
while(1) {
int a = rand() % 1000;
int b = rand() % 1000;
printf("gen %d %d\n", a, b);
fprintf(stderr, "err, gen %d %d\n", a, b);
sleep(1);
}
}
else {
cons = fork();
if (cons < 0) {
// fork error
close(fd[READ_END]);
close(fd[WRITE_END]);
kill(gen, SIGKILL);
exit(2);
} else if (cons == 0) {
// cons child
close(fd[WRITE_END]);
dup2(fd[READ_END], STDIN_FILENO);
close(fd[READ_END]);
char line[BUF_SIZE];
while (fgets(line, sizeof(line), stdin)) {
printf("cons received: %s\n", line);
fprintf(stderr, "cons lives!\n");
}
} else {
// parent
close(fd[READ_END]);
close(fd[WRITE_END]);
sleep(5);
kill(gen, SIGTERM);
}
}
return 0;
}
Upvotes: 2
Views: 1905
Reputation: 148910
Standard output is by default buffered, so your gen child only queues output for later sending. So you must fflush
it to force your messages to be immedialely delivered:
...
printf("gen %d %d\n", a, b);
fprintf(stderr, "err, gen %d %d\n", a, b);
fflush(stdout); // <= force immediate send
sleep(1);
...
Upvotes: 1