Fix for ZipArchive depending on Position for Create streams#12682
Fix for ZipArchive depending on Position for Create streams#12682ianhays merged 3 commits intodotnet:masterfrom StephenCleary:master
Conversation
…n for non-seekable streams. This causes test failure due to issue #11497.
|
Hi @StephenCleary, I'm your friendly neighborhood .NET Foundation Pull Request Bot (You can call me DNFBOT). Thanks for your contribution! TTYL, DNFBOT; |
|
@StephenCleary, Thanks for signing the contribution license agreement so quickly! Actual humans will now validate the agreement and then evaluate the PR. |
|
@ianhays can you please CR? |
|
@ianhays PTAL |
|
Looks like goodness to me. I'm somewhat concerned by the overhead of creating the wrapper stream, but considering the old behavior I think it's admissible.
@StephenCleary what do you mean by this? We didn't have any tests failing because of this issue. It would be ideal to have a test added that fails with the old behavior but passes with the new behavior. |
|
I was also hesitant about the wrapper stream, but the alternative would be to have The first checkin in this pull request fixes the unit tests so that they fail due to this bug. So there are now unit tests that will detect a regression. |
|
@ianhays please hit merge if you're good.. |
|
Thanks for the contribution @StephenCleary, I tend to agree on this being preferable to manually tracking the position. Merging. |
|
|
||
| public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) | ||
| { | ||
| _position += count; |
There was a problem hiding this comment.
What if the operation is canceled... won't the position then be incorrect?
Same comment/question would apply as well to exceptions in other operations.
There was a problem hiding this comment.
Yes, but what would the correct position be in that case?
There was a problem hiding this comment.
There's the same issue for when the synchronous Write flat out fails. I considered saying we should update the position after the underlying call, but we would have to do something special for the async Write for that.
There was a problem hiding this comment.
but what would the correct position be in that case?
We can't know, but that also means we'd be reporting potentially incorrect results from Position, and I don't know enough about the codebase to know what that could mess up. I'm wondering if on cancellation/failure, we should set _position to a sentinel value (e.g. -1) and change get_Position to do if (_position < 0) throw ...; else return _position;. It may not be worth it if nothing bad would come of it, but we should understand it better.
There was a problem hiding this comment.
I like that idea; it's the only approach that really makes sense.
It also takes this class a step closer to being a generic (read/write) position tracking stream wrapper, which may actually make sense to eventually expose (in a more general package).
|
|
||
| namespace System.IO.Compression | ||
| { | ||
| internal sealed class PositionPreservingWriteOnlyStreamWrapper : Stream |
There was a problem hiding this comment.
Nit: I'd drop the "Wrapper" suffix. There are a variety of streams that wrap other streams and that don't use a suffix like this, e.g. DeflateStream, BufferedStream, etc.
|
|
||
| public override void WriteByte(byte value) | ||
| { | ||
| _position += 1; |
|
Pardon my ignorance regarding pull requests, but I'd like to apply the suggestions from @stephentoub. Since this is already merged, that would have to be a new pull request, right? |
Correct. |
|
I'm pinging here as well because communication on Connect is dodgy. |
Fix for ZipArchive depending on Position for Create streams Commit migrated from dotnet/corefx@e8c0e78
This is a fix for #11497, using the stream wrapper technique suggested by @svick.
The stream wrapper is only applied when necessary (if the
ZipArchiveis opened inCreatemode and the underlying stream does not support seeking).The wrapper forwards all (non-reading) methods to its base stream, including asynchronous methods. This is important to prevent the wrapper from forcing synchrony.
The existing unit tests (once fixed) were sufficient to detect this bug.