I spawn a child process using pipe(), fork(), dup(), execve().
From the parent, is it safe to wait for stdin and stdout of the child to close (i.e. read() return 0 on both), and then do waitpid() to collect the termination status?
Or can it happen that the process will fail without ever closing stdin and stdout? (thus my program never getting to waitpid)
To clarify, I'm asking whether the following is safe:
while (child_stdin != -1 && child_stdout != -1) {
poll(...)
if (got_stdout) {
n = read(child_stdout);
if (n >= 0) {
// do something with output
} else if (n == 0) {
child_stdout = -1
}
}
// same for stdin
}
waitpid(child_pid)
Or can it happen that child will terminate, but I'll never get 0 on read() or write().
No signals are involved, just poll()-ing.
Closing stdin by pressing Ctrl+D, is a thing you can do during readline #30790.
In computer programming, standard streams are interconnected input and output communication channels between a computer program and its environment when it begins execution. The three input/output (I/O) connections are called standard input (stdin), standard output (stdout) and standard error (stderr).
Every process is initialized with three open file descriptors called stdin , stdout , and stderr .
stdin − It stands for standard input, and is used for taking text as an input. stdout − It stands for standard output, and is used to text output of any command you type in the terminal, and then that output is stored in the stdout stream. stderr − It stands for standard error.
If process a
spawns process b
, and process b
spawns process c
(so c
is the grandchild of a
), b
can terminate and close its copy of the file descriptor that was its stdout (presumably, b's
stdout is the write side of a pipe that a
is watching.) But c
still has that pipe open, so a
will get the SIGCHLD from b
, but will not get EOF on the pipe. In other words, yes, it can happen that the child terminates but the parent does not see the pipe close.
Also, it is a common coding error that a
still has the write side of the pipe open. In that case, b
can terminate and close its copy of the write side of the pipe, but the parent never sees the pipe close because the parent is keeping it open.
All file descriptors are closed by the system at process exit. What can happen, is that there is some output stored in buffers, which has not been flushed.
If the child process never terminates, then it can happen, that your parent waits forever and never reaches waitpid()
.
Edit:
When your child terminates, all descriptors are closed and then you will finally get 0 on read()
(or -1 if something went wrong!). So, you might want to change to:
...
if (n > 0) {
// do something with output
} else if (n <= 0) {
child_stdout = -1
}
Your code won't terminate though, because of:
if (n >= 0) { // n > 0 || n == 0
// ...
} else if (n == 0) {
// Never reached!
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With