GeezerVison is showing github.com — os.dup2() raises wrong OSError for negative fds · Issue #102179 · python/cpython
os.dup2() raises wrong OSError for negative fds #102179Description
>>> os.dup2(-1, 0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: [Errno 0] Error
The bug is caused by the old manual sign check that at some point lost the part that set errno:
|
if (fd < 0 || fd2 < 0) { |
|
posix_error(); |
|
return -1; |
I'm going to submit a PR with the fix.
Linked PRs
Activityizbyshev commented on Mar 4, 2023 ContributorAuthor More actions It turned out that on wasm32-emscripten dup2() for negative fds is currently broken. I could reproduce that with the C equivalent of the failed test case and the latest emsdk:
$ ./emsdk list | grep INSTALLED
3.1.32 INSTALLED
3.1.32 INSTALLED
* sdk-releases-29ad1037cd6b99e5d8a1bd75bc188c1e9a6fda8d-64bit INSTALLED
(*) releases-29ad1037cd6b99e5d8a1bd75bc188c1e9a6fda8d-64bit INSTALLED
(*) node-14.18.2-64bit INSTALLED
$ cat t.c
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main() {
int valid_fd = open(".", O_RDONLY);
if (valid_fd < 0) {
perror("open");
return 1;
}
int fds[] = {
valid_fd,
-1,
INT_MIN,
};
for (int i = 0; i < sizeof fds / sizeof *fds; i++)
for (int j = 0; j < sizeof fds / sizeof *fds; j++)
if (i != j) {
int fd = fds[i], fd2 = fds[j];
printf("dup2(%d, %d): ", fd, fd2);
errno = 0;
if (dup2(fd, fd2) < 0) {
printf("%d (%s)\n", errno, strerror(errno));
} else {
printf("succeeded\n");
}
}
}
$ emcc t.c
$ node a.out.js
dup2(3, -1): 1 (Argument list too long)
dup2(3, -2147483648): 0 (No error information)
dup2(-1, 3): succeeded
dup2(-1, -2147483648): 0 (No error information)
dup2(-2147483648, 3): succeeded
dup2(-2147483648, -1): 1 (Argument list too long)
Apparently, in Emscripten there is ongoing work on WASMFS which fixed this particular issue, and comments in this PR additionally confirm that dup2() is broken in the current default FS implementation.
Indeed, compiling with -sWASMFS makes the test work as expected:
$ emcc -sWASMFS t.c
$ node a.out.js
dup2(3, -1): 8 (Bad file descriptor)
dup2(3, -2147483648): 8 (Bad file descriptor)
dup2(-1, 3): 8 (Bad file descriptor)
dup2(-1, -2147483648): 8 (Bad file descriptor)
dup2(-2147483648, 3): 8 (Bad file descriptor)
dup2(-2147483648, -1): 8 (Bad file descriptor)
Given the current state of Emscripten, I don't think we should care that os.dup2() will start to behave differently after removing the manual fd check in CPython. I propose to simply skip the failed test case on Emscripten.
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|