Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getdents[64] misses last entries if some entries are removed between successive calls #3805

Closed
izbyshev opened this issue Jan 27, 2019 · 1 comment
Labels

Comments

@izbyshev
Copy link

I'm running Windows 10 1809 10.0.17763.1 (with Ubuntu 18.04) and I've hit what seems to be a variant of #2077. When reading /proc/self/fd, if there are several getdents[64] syscalls and we close some of the descriptors corresponding to the entries we've got after each syscall, we'll stop early.

$ cat test.c
#define _GNU_SOURCE
#include <fcntl.h>
#include <sys/syscall.h>
#include <unistd.h>

int main(void) {
    char buf[100];
    for (int i = 0; i < 10; i++)
        open("/dev/null", O_RDONLY);
    int dfd = open("/proc/self/fd", O_RDONLY);
    int fd = 4;
    while (syscall(SYS_getdents64, dfd, buf, sizeof(buf)) > 0)
        close(fd++);
    close(dfd);
    return 0;
}
$ gcc test.c
$ strace -e openat,close,getdents64 ./a.out
[...]
openat(AT_FDCWD, "/proc/self/fd", O_RDONLY) = 13
getdents64(13, /* 4 entries */, 100)    = 96
close(4)                                = 0
getdents64(13, /* 4 entries */, 100)    = 96
close(5)                                = 0
getdents64(13, /* 4 entries */, 100)    = 96
close(6)                                = 0
getdents64(13, /* 1 entries */, 100)    = 24
close(7)                                = 0
getdents64(13, /* 0 entries */, 100)    = 0
close(13)                               = 0
[...]

The expected strace output is:

openat(AT_FDCWD, "/proc/self/fd", O_RDONLY) = 13
getdents64(13, /* 4 entries */, 100)    = 96
close(4)                                = 0
getdents64(13, /* 4 entries */, 100)    = 96
close(5)                                = 0
getdents64(13, /* 4 entries */, 100)    = 96
close(6)                                = 0
getdents64(13, /* 3 entries */, 100)    = 72
close(7)                                = 0
getdents64(13, /* 0 entries */, 100)    = 0
close(13)                               = 0

The example was reduced from subprocess Python module. Its test suite fails because subprocess uses similar logic to close open descriptors in the child process.

getdents syscall is also affected.

Copy link
Contributor

This issue has been automatically closed since it has not had any activity for the past year. If you're still experiencing this issue please re-file this as a new issue or feature request.

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants