emscripten-core / emscripten-core/emscripten
Got "Resource temporarily unavailable" when reading empty pipe
- Dominant language
- C++
- Stars
- 27.6k
- Forks
- 3.6k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 105
Description
Please include the following in your bug report:
**Version of emscripten/emsdk:**
3.1.54
**Failing command line in full:**
```shell
# emscripten
emcc read_pipe.cpp -o main.js
node main.js
# g++
g++ read_pipe.cpp -o main
./main
```
Hi, I was trying to use `pipe` and found a weird thing. I tried to use some syscalls (`read`, `getc`, `getc_unlocked`, etc.) to read from the read end of the pipe.
I found if I tried to read from the pipe when it was empty, then the `errno` was set to be 6, i.e.,`Resource temporarily unavailable`.
Moreover, for the `read` syscall, the return value turns out to be `-1`. However, according to https://man7.org/linux/man-pages/man2/read.2.html#RETURN_VALUE, the return value should be 0 and the `errno` shouldn't be set
For `getc` and `getc_unlocked`, the `errno` is also set the same as above when reading the empty pipe, and I further checked the `ferror(f)`, where `f` refers to the pipe's read end, and it turn out to be `-1`.
Please check the codes and results posted below for details.
I believe we should expect no error message when reading from the empty pipe. Such an issue would be a disturbance while using these return values, errno, etc.
It'd be so appreciated if you could check it. Thank you!
#### Code
**Here is the case using `read` to read an empty pipe**
```c++
#include
#include
#include
#include
#include
#include
int main(int argc, char** argv) {
int pipefd[2];
::pipe(pipefd);
std::string input = "x";
::write(pipefd[1], input.c_str(), input.size());
close(pipefd[1]);
printf("Begining, error?: %s\n", strerror(errno));
FILE* f = ::fdopen(pipefd[0], "r");
char buf[10];
int result = read(pipefd[0], buf, 1);
printf("the pipe now is not empty! buf: %s, result: %d, ferror: %d, error: %s\n",
buf, result, ferror(f), strerror(errno));
char buf1[10];
result = read(pipefd[0], buf, 1); // pipe is empty now
printf("the pipe is empty now! buf: %s, result: %d, ferror: %d, error: %s\n",
buf1, result, ferror(f), strerror(errno));
return 0;
}
```
#### Results
And I got the execution results by wasm and native execution as follows.
Here for the native execution, there's no error, which meets the expectation.
But for the wasm execution, we got the `Resource temporarily unavailable`, and the return value of the `read` is `-1` when reading the empty pipe.
``` shell
# emscripten
Begining, error?: No error information
the pipe now is not empty! buf: x, result: 1, ferror: 0, error: No error information
the pipe is empty now! buf: , result: -1, ferror: 0, error: Resource temporarily unavailable
# g++
Begining, error?: Success
the pipe now is not empty! buf: x, result: 1, ferror: 0, error: Success
the pipe is empty now! buf: , result: 0, ferror: 0, error: Success
```
### The case of `getc_unlocked`
Basically it's just similar to the first case, just I use `getc_unlocked` to read. In this case, the results are similar, and furthermore, the `ferror(f)` returns -1 if it's run with wasm.
```c++
#include
#include
#include
#include
#include
#include
int main(int argc, char** argv) {
int pipefd[2];
::pipe(pipefd);
std::string input = "x";
::write(pipefd[1], input.c_str(), input.size());
close(pipefd[1]);
FILE* f = ::fdopen(pipefd[0], "r");
printf("after fdopen, ferror: %d, error: %s\n", ferror(f), strerror(errno));
int result = getc_unlocked(f);
printf("the pipe now is not empty! result: %d, ferror: %d, error: %s\n", result, ferror(f), strerror(errno));
result = getc_unlocked(f);
printf("the pipe is empty now! result: %d, ferror: %d, error: %s\n", result, ferror(f), strerror(errno));
return 0;
}
```
And the results are as follow. The return values for wasm execution here are all correct, but the `ferror(f)` turns out to be -1 when the pipe is empty.
```shell
# wasm
after fdopen, ferror: 0, error: No error information
the pipe now is not empty! result: 120, ferror: 0, error: No error information
the pipe is empty now! result: -1, ferror: 1, error: Resource temporarily unavailable
# native
after fdopen, ferror: 0, error: Success
the pipe now is not empty! result: 120, ferror: 0, error: Success
the pipe is empty now! result: -1, ferror: 0, error: Success
```
Contributor guide
Assessment
This issue has not been assessed yet.