-
Notifications
You must be signed in to change notification settings - Fork 3.4k
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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
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.