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
std: Fix using fs.Dir.Iterator
twice
#10404
Conversation
I take it that #10317 is still not fixed hence why the CI fails with this test added? If that's the case, I see two solutions for this PR to be in mergable state: 1) if you're up for it, you could propose a fix to #10317, or 2) disable this test for the time being an leave a TODO comment referencing the issue. Lemme know what you think! |
i think |
Yep, sorry, my PRs have fallen behind. I'll get this sorted in a moment to be merged. |
I'd like to see the Windows CI pass before this is merged, to be sure :) |
Ok, ready to merge! @kubkon |
fs.Dir.Iterator
twicefs.Dir.Iterator
twice
lib/std/fs.zig
Outdated
@@ -369,6 +370,10 @@ pub const Dir = struct { | |||
fn nextSolaris(self: *Self) !?Entry { | |||
start_over: while (true) { | |||
if (self.index >= self.end_index) { | |||
if (self.first) { | |||
std.os.lseek_SET(self.dir.fs, 0) catch unreachable; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we sure this cannot fail?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It definitely can't on Linux, I assumed POSIX compliant systems would be the same, though I just pushed this to see how the tests run.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think an explanatory comment on each catch unreachable
would be nice, but the possible errors for each platform are (from lseek(2)
):
EBADF
when Dir.fd is invalid or wasn't opened with iteration. Thiscatch unreachable
would show up later anyway during thenext
call (see here and other similar lines), so it being triggered during thelseek_SET
just moves where it happens.EINVAL
when "whence is not valid or the resulting file offset would be negative, or beyond the end of a seekable device.", but we're always using the known-to-be-validSEEK_SET
and the offset is always0
EOVERFLOW
when "The resulting file offset cannot be represented in an off_t", but we know0
will be the resulting file offsetENXIO
when lseek is usingSEEK_DATA
orSEEK_HOLE
(actually, this isn't even a possible error within lseek_SET since we know we're usingSEEK_SET
)ESPIPE
when "fd is associated with a pipe, socket, or FIFO.", but we knowfd
is a directory
WASI has an additional ENOTCAPABLE
that I'm unsure about when/if it can be triggered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I see. Curious to see if it applies to BSD/macOS too. I remember in the past I had some mixed experience with Dir iterators on macOS - the way the dir pointer works was completely different to how it works on Linux. But let's see if the tests pass. If so, then we're golden!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, worth looking further into this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think an explanatory comment on each
catch unreachable
would be nice, but the possible errors for each platform are (fromlseek(2)
):
EBADF
when Dir.fd is invalid or wasn't opened with iteration. Thiscatch unreachable
would show up later anyway during thenext
call (see here and other similar lines), so it being triggered during thelseek_SET
just moves where it happens.EINVAL
when "whence is not valid or the resulting file offset would be negative, or beyond the end of a seekable device.", but we're always using the known-to-be-validSEEK_SET
and the offset is always0
EOVERFLOW
when "The resulting file offset cannot be represented in an off_t", but we know0
will be the resulting file offsetENXIO
when lseek is usingSEEK_DATA
orSEEK_HOLE
(actually, this isn't even a possible error within lseek_SET since we know we're usingSEEK_SET
)ESPIPE
when "fd is associated with a pipe, socket, or FIFO.", but we knowfd
is a directoryWASI has an additional
ENOTCAPABLE
that I'm unsure about when/if it can be triggered.
ENOTCAPABLE
would be triggered when we want iterate a dir tree we weren't given capabilities to do so.
Made changes, noticed I skipped over WASI and Darwin, so they should be sorted now :) |
Am confused what went on with the Linux CI there. Seems to have failed on code which I didn't touch :/ |
Will just push this to rerun CI |
maybe rebase |
Already did that. This is so odd. Maybe I'll try reverting the changes I did to the WASI impl, see if that does anything... |
7674ef6
to
e3260c2
Compare
Seems to have done it. Somehow using |
It looks like Line 789 in 0e6d218
which then gets used when calling
The current implementation with no changes already passes the |
Fantastic, thank you for explaining that to me! With that, this should be ready to merge. |
This fixes the use of multiple `Iterator`s in a row on a directory. Previously, on many platforms, using an `Iterator` on an already-iterated directory would give no entries. Fixing this involved seeking to the beginning of the directory on the first call of `next()`.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great @ominitay ! Thank you for seeing it through!
std: Fix using `fs.Dir.Iterator` twice
This fixes the use of multiple
Iterator
s in a row on a directory. Previously, on many platforms, using anIterator
on an already-iterated directory would give no entries.Fixing this involved seeking to the beginning of the directory on the first call of
next()
.cc: @nektro @squeek502
fixes #10317