emscripten-core / emscripten-core/emscripten
pipe() doesn't create a blocking pipe
- Dominant language
- C++
- Stars
- 27.6k
- Forks
- 3.6k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 105
Description
On Emscripten, when reading from a pipe created via `pipe()`, the `read()` call returns immediately with `EAGAIN` when there's no data in the pipe. This contradicts the standard behavior specified by POSIX:
> EAGAIN The file descriptor fd refers to a file other than a
> socket and has been marked nonblocking (O_NONBLOCK), and
> the read would block. See open(2) for further details on
> the O_NONBLOCK flag.
> EAGAIN or EWOULDBLOCK
> The file descriptor fd refers to a socket and has been
> marked nonblocking (O_NONBLOCK), and the read would block.
https://man7.org/linux/man-pages/man2/read.2.html
> If a process attempts to read from an empty pipe, then read(2)
> will block until data is available. <...>
> Nonblocking I/O is possible by using the fcntl(2)
> F_SETFL operation to enable the O_NONBLOCK open file status flag.
https://man7.org/linux/man-pages/man7/pipe.7.html
Given that `pipe()` doesn't set the `O_NONBLOCK` flag, I believe the Emscripten's behavior with returning `EAGAIN` is wrong.
Sample program:
```
#include
#include
#include
int main(int argc, char** argv) {
int pipefd[2];
if (pipe(pipefd)) {
perror("pipe() failed");
exit(-1);
}
if (argc > 1) {
char c = 0;
if (write(pipefd[1], &c, 1) != 1) {
perror("write() failed");
exit(-1);
}
}
char c;
if (read(pipefd[0], &c, 1) != 1) {
perror("read() failed");
exit(-1);
}
exit(0);
}
```
This program, when run under Emscripten, fails with "Resource temporarily unavailable". When the same program is run on Linux using standard g++ and libc, it correctly blocks in `read()`.
P.S. The program also demonstrates that, in case `write()` was previously called, the data is successfully read from it under Emscripten.
Contributor guide
Assessment
This issue has not been assessed yet.