emscripten-core / emscripten

Emscripten: An LLVM-to-WebAssembly Compiler
Other
25.67k stars 3.29k forks source link

Expect error if closing a file twice with `::close` and `::fclose` sequentially, but got nothing #22033

Closed hly2019 closed 4 months ago

hly2019 commented 4 months ago

Please include the following in your bug report:

Version of emscripten/emsdk: 3.1.54

Failing command line in full:

# emscripten:
emcc close_fclose.cpp -o main.js --preload-file ./temp.txt; node main.js

# g++:
g++ close_fclose.cpp -o main; ./main

Hi, I found a problem regarding the behaviour of ::fclose and ::close. Basically, if we first close a file with ::close, then call ::fclose to close it again, it is definitely a behavior not allowed and should report errors via errno and the return value of the ::fclose should be EOF according to https://man7.org/linux/man-pages/man3/fclose.3.html#RETURN_VALUE. However, it seems such operations don't set anything with errno, and the return value of ::fclose is also not set as EOF, as shown below, which seems to be weird. Besides, if we reverse the order of ::close and ::fclose (i.e., first execute ::fclose, then ::close), then I could get a correct error message via errno and the return value of ::close is EOF. So it's quite weird.

It'd be so appreciated if you could help check it. Thank you!

Code

#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

int main() {
    FILE* f = ::fopen("temp.txt", "r");
    int fd = fileno(f);
    // interesting: if call fclose(f) before close(fd), it could reports error
    int ret_1 = close(fd);
    int ret_2 = fclose(f);
    printf("error: %s\n", strerror(errno));
    printf("ret_of_close is: %d, ret_of_fclose is: %d\n", ret_1, ret_2);
    return 0;
}

Result

Here we can see in wasm execution results, there is no error information, and the return value of ::fclose is also not EOF.

# emscripten
error: No error information
ret_of_close is: 0, ret_of_fclose is: 8

# g++
error: Bad file descriptor
ret_of_close is: 0, ret_of_fclose is: -1
sbc100 commented 4 months ago

This looks like an oversight/bug in musl's implementation of fclose. See: https://github.com/emscripten-core/emscripten/blob/1801e94f5f35aad3ba341897d619d8ca11d26e0f/system/lib/libc/musl/src/stdio/fclose.c#L11-L14 https://github.com/emscripten-core/emscripten/blob/1801e94f5f35aad3ba341897d619d8ca11d26e0f/system/lib/libc/musl/src/stdio/__stdio_close.c#L11-L18