It's very odd - but if I replace the first printf with a write, then it all works for me.
Code:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#define PIPE_RD 0
#define PIPE_WR 1
int main() {
char line[100];
int p[3][2];
pid_t pids[3];
pipe(p[0]); pipe(p[1]); pipe(p[2]);
// proc 1
if ( (pids[0]=fork()) == 0) {
int in = 0, out = 1, spare = 2;
dup2(p[in][PIPE_RD], 0); dup2(p[out][PIPE_WR], 1);
close(p[in][PIPE_WR]); close(p[out][PIPE_RD]);
close(p[spare][PIPE_RD]); close(p[spare][PIPE_WR]);
//printf("hello\n"); // write to proc2
write(1,"world\n",6);
fgets(line, sizeof line, stdin); // read from proc3
fprintf(stderr, "1: %s\n", line);
return 0;
}
// proc 2
if ( (pids[1]=fork()) == 0) {
int in = 1, out = 2, spare = 0;
dup2(p[in][PIPE_RD], 0); dup2(p[out][PIPE_WR], 1);
close(p[in][PIPE_WR]); close(p[out][PIPE_RD]);
close(p[spare][PIPE_RD]); close(p[spare][PIPE_WR]);
fgets(line, sizeof line, stdin); // read from proc1
printf("AA:%s", line); // write to proc3
fprintf(stderr, "2: %s\n", line);
return 0;
}
// proc 3
if ( (pids[2]=fork()) == 0) {
int in = 2, out = 0, spare = 1;
dup2(p[in][PIPE_RD], 0); dup2(p[out][PIPE_WR], 1);
close(p[in][PIPE_WR]); close(p[out][PIPE_RD]);
close(p[spare][PIPE_RD]); close(p[spare][PIPE_WR]);
fgets(line, sizeof line, stdin); // read from proc2
printf("BB:%s", line); // write to proc1
fprintf(stderr, "3: %s\n", line);
return 0;
}
close(p[0][PIPE_RD]); close(p[0][PIPE_WR]);
close(p[1][PIPE_RD]); close(p[1][PIPE_WR]);
close(p[2][PIPE_RD]); close(p[2][PIPE_WR]);
int status;
pid_t q;
printf("Waiting for children %d %d %d\n", pids[0],pids[1],pids[2]);
q = waitpid(-1,&status,0);
printf("Child %d exited with %d\n", q, WEXITSTATUS(status));
q = waitpid(-1,&status,0);
printf("Child %d exited with %d\n", q, WEXITSTATUS(status));
q = waitpid(-1,&status,0);
printf("Child %d exited with %d\n", q, WEXITSTATUS(status));
return 0;
}
$ gcc -Wall -g foo.c
$ ./a.out
Waiting for children 4514 4515 4516
2: world
Child 4515 exited with 0
3: AA:world
Child 4516 exited with 0
1: BB:AA:world
Child 4514 exited with 0
It's like the printf doesn't happen?
I mean, even if I run "strace -f ./a.out", it doesn't show up.
Code:
pipe([3, 4]) = 0
pipe([5, 6]) = 0
pipe([7, 8]) = 0
clone(strace: Process 4279 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7ff17fd1b9d0) = 4279
[pid 4279] dup2(3, 0) = 0
[pid 4279] dup2(6, 1) = 1
[pid 4279] close(4) = 0
[pid 4279] close(5) = 0
[pid 4279] close(7) = 0
[pid 4279] close(8) = 0
[pid 4279] fstat(1, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
[pid 4278] clone( <unfinished ...>
[pid 4279] brk(NULL) = 0x1a5a000
[pid 4279] brk(0x1a7c000) = 0x1a7c000
[pid 4279] fstat(0, strace: Process 4280 attached
<unfinished ...>
[pid 4278] <... clone resumed> child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7ff17fd1b9d0) = 4280
[pid 4279] <... fstat resumed> {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
[pid 4279] read(0, <unfinished ...>
I would have expected the printf() to call the underlying write() system call, but it's not there.
So the whole ring locks up waiting on read() calls.
But with write(), it's all as expected!
Code:
pipe([3, 4]) = 0
pipe([5, 6]) = 0
pipe([7, 8]) = 0
clone(strace: Process 4557 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fd3909779d0) = 4557
[pid 4557] dup2(3, 0 <unfinished ...>
[pid 4556] clone( <unfinished ...>
[pid 4557] <... dup2 resumed> ) = 0
[pid 4557] dup2(6, 1) = 1
[pid 4557] close(4) = 0
[pid 4557] close(5) = 0
[pid 4557] close(7) = 0
[pid 4557] close(8strace: Process 4558 attached
<unfinished ...>
[pid 4556] <... clone resumed> child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fd3909779d0) = 4558
[pid 4557] <... close resumed> ) = 0
[pid 4557] write(1, "world\n", 6) = 6
[pid 4557] fstat(0, <unfinished ...>
[pid 4558] dup2(5, 0 <unfinished ...>
[pid 4556] clone( <unfinished ...>
[pid 4557] <... fstat resumed> {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
[pid 4557] brk(NULL) = 0x249d000
[pid 4558] <... dup2 resumed> ) = 0
[pid 4557] brk(0x24bf000) = 0x24bf000
[pid 4556] <... clone resumed> child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fd3909779d0) = 4559
strace: Process 4559 attached
[pid 4558] dup2(8, 1 <unfinished ...>
[pid 4557] read(0, <unfinished ...>
///
[pid 4557] <... read resumed> "BB:AA:world\n", 4096) = 12
The bootstrap write() call happens, and the ring runs to completion.