Subprocess doesn't get stdin sometimes.
Ilya Kazakevich <[email protected]>
| Newsgroups | org.kernel.vger.dash |
|---|---|
| Message-ID | <CAMQsgbSZnEac=ETYnR6a_ysnAysaHThwY03pnoDxC=p5FqtAag@mail.gmail.com> |
Hello,
I am not sure if it is a `dash` bug or my scenario isn't correct (it
works with `bash`, however).
I execute command that reads N bytes and send this bytes directly
after execution, i.e `head -c 2 \n ab`
Here is a showcase: it forks shell , sends data and reads output
```
#include <stdio.h>
#include <unistd.h>
#include <string.h>
static void child(int read_pipe, int write_pipe) {
dup2(write_pipe, STDOUT_FILENO);
dup2(read_pipe, STDIN_FILENO);
execlp("/bin/bash", "/bin/bash", NULL);
}
static void parent(int read_pipe, int write_pipe) {
char buf[] = "head -c 2\n";
write(write_pipe, buf, sizeof buf - 1);
char buf2[] = "ab\n";
write(write_pipe, buf2, sizeof buf2 - 1);
char answer[112] = {0};
read(read_pipe, answer, sizeof answer);
answer[sizeof answer - 1] = 0;
printf("%s", answer);
}
int main() {
int to_process[2];
pipe(to_process);
int to_process_read_pipe = to_process[0];
int to_process_write_pipe = to_process[1];
int from_process[2];
pipe(from_process);
int from_process_read_pipe = from_process[0];
int from_process_write_pipe = from_process[1];
if (fork() == 0) {
close(from_process_read_pipe);
close(to_process_write_pipe);
child(to_process_read_pipe, from_process_write_pipe);
} else {
close(to_process_read_pipe);
close(from_process_write_pipe);
parent(from_process_read_pipe, to_process_write_pipe);
}
}
```
It works perfectly for `bash`.
If I use `dash` -- it freezes. In `strace` I see that `dash` calls
`vfork` followed by `execve`.
`head` then calls `read` and waits forever.
However: when I insert `sleep(1);` after the first `write(..."head..)` it works!
It seems that we have a race condition here: I should have "waited"
before stdin got connected to the new child. If I write data too
early, it simply drops and never reaches the child.
A couple of questions:
1. Is it a bug or do I simply misuse shell? Should it work? I haven't
found any POSIX statement that confirms so.
2. I am curious: why use `vfork` nowadays? `bash` uses `close`.
Thank you.
Ilya.