Repository navigation
Fix Reader.Limited hangs - #25109
Fix Reader.Limited hangs#25109whatisaphone wants to merge 2 commits into
Conversation
|
It might not be appropriate to short-circuit a zero byte stream() in all cases? I think there are some use cases where reading zero bytes is actually valuable, to check if a file descriptor is working or something like that? I'm not sure. |
Wouldn't these use cases already break in the general case, with potential composition of multiple readers/writers, buffering, compression etc.? |
|
|
||
| fn stream(r: *Reader, w: *Writer, limit: Limit) Reader.StreamError!usize { | ||
| const l: *Limited = @fieldParentPtr("interface", r); | ||
| if (l.remaining == .nothing) return error.EndOfStream; |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
There was a problem hiding this comment.
Right now reading 0 bytes is a no-op, not an error. It's like subtracting 0 from a number. I don't think that should change.
There was a problem hiding this comment.
Ah, my bad, I confused the interface implementation function here (in Reader/Limited.zig) with the user-facing stream function in the interface Reader.zig.
Reader.stream already returns 0 if limit == .nothing was passed, in that case this function isn't called - all good then, sorry for the noise.
(We could document and assert(limit != .nothing); here in the implementation functions, but that's probably deemed unnecessary.)
| if (limit == .nothing) { | ||
| @branchHint(.unlikely); | ||
| return 0; | ||
| } |
There was a problem hiding this comment.
This should not be logic inside the interface. To enforce this rule, it must be an assertion. There's already an assertion below for this on line 183 but it will be skipped if an error is returned. I suggest instead of this to do the assertion after calling stream but before returning an error. Also, this rule must be mentioned in the VTable documentation for stream.
|
When I first posted this, ec636c3 was definitely a prerequisite for c95d2b7 to work, but it seems that's changed since then. The tests pass fine on my commit b9f8b6e from #25512, without needing ec636c3. What's weird is the new tests still pass even if I completely remove my change in At any rate I'm fine closing this in favor of #25512 and we can consider the two linked bugs fixed once that's merged. But do note this line is useless now. I suggest there's some follow-on work of figuring out the |
|
Another thing worth noting: not doing the 0 check in stream interface is required in order for the fix in #25162 to resolve the ambiguity between |
|
Funny you should say that, because I just tried the test from that commit transplanted to b9f8b6e, and it fails because |
Fixes #24932, #25093
I'm not 100% sure on the approach, but it does fix those bugs, and the tests pass (and it also fixes my real world project)
It used to be that in
Reader.stream, if there is buffered data but you pass a limit of 0,limit.slicewould return a buffer with len == 0, then it would fall through the buffer.len check and callvtable.stream(endingStream) even though the stream hadn't ended. That doesn't seem right to me.I believe that issue masked the two linked bugs in certain conditions, which is why as of 0.15.1 you need a custom Reader or a third intermediary stream to expose them, something like this:
After the first commit, the linked bugs were straightforward to repro and write tests for in the second commit.