I try to make 2 children of process to communicate:
void demo() {
int pipes[2];
int create_pipe_status = pipe(pipes);
int status;
pid_t fork_id = fork();
if(!fork_id) {
//parent
status = dup2(pipes[1], STDOUT_FILENO);
close(pipes[0]);
close(pipes[1]);
}
pid_t fork_id2 = fork();
if(!fork_id2){
//child
status = dup2(pipes[0], STDIN_FILENO);
close(pipes[0]);
close(pipes[1]); //keep
}
wait(NULL);
wait(NULL);
}
and when I try to close the file descriptors associated with the pipe I get the error EBADF
(bad file descriptor) in errno
.
What is my mistake?
First, the existing process calls fork()
, then this original process and its forked child both call fork()
again resulting in four processes in total. That is, the processes are:
fork()
.fork()
.fork()
.As a result, the code block (i.e., the second if
block) is executed by the child process of the child process:
if(!fork_id2){
//child
status = dup2(pipes[0], STDIN_FILENO);
close(pipes[0]);
close(pipes[1]);
}
This child process of the child process tries to close pipe[0]
and pipe[1]
. However, the child process (i.e., the parent process of the child of the child) has already closed both pipe[0]
and pipe[1]
. This is where the bad file descriptor error comes from, i.e., closing the file descriptor twice.
Note that even though the second child of the original process also executes this code block, it doesn't suffer from this issue because the original process hasn't closed the pipe file descriptors at the moment of calling fork()
for the second time, so both file descriptors are still open when the second child of the original process closes them.
I guess what you actually want is two create two children processes from an existing process. If so, then just limit the second call to fork()
to the parent process (i.e., the original process):
void demo() {
int pipes[2];
int create_pipe_status = pipe(pipes);
int status;
pid_t fork_id = fork();
if (!fork_id) { // 1st child
status = dup2(pipes[1], STDOUT_FILENO);
assert(!close(pipes[0]));
assert(!close(pipes[1]));
} else {
// parent
pid_t fork_id2 = fork();
if (!fork_id2) { // 2nd child
status = dup2(pipes[0], STDIN_FILENO);
assert(!close(pipes[0]));
assert(!close(pipes[1]));
} else { // parent
assert(!close(pipes[0]));
assert(!close(pipes[1]));
}
}
wait(NULL);
wait(NULL);
}