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

XpsDocumentWriter.Write fails with NotSupportedException #1363

Closed
thomasclaudiushuber opened this issue Jul 24, 2019 · 21 comments
Closed

XpsDocumentWriter.Write fails with NotSupportedException #1363

thomasclaudiushuber opened this issue Jul 24, 2019 · 21 comments
Assignees
Labels
issue-type-tracking-external To track dependencies with other teams or repos rank20 Rank: Priority/rank on a scale of (1..100)
Milestone

Comments

@thomasclaudiushuber
Copy link
Contributor

thomasclaudiushuber commented Jul 24, 2019

  • .NET Core Version: 3.0.100-preview8-013410
  • Windows version: 1903
  • Does the bug reproduce also in WPF for .NET Framework 4.8?: No

Problem description:
XpsDocumentWriter.Write fails with NotSupportedException with the message "This stream from ZipArchiveEntry does not support seeking."

Actual behavior:
Message:
System.NotSupportedException : This stream from ZipArchiveEntry does not support seeking.
Stack Trace:
at WrappedStream.ThrowIfCantSeek()
at WrappedStream.SetLength(Int64 value)
at ZipWrappingStream.SetLength(Int64 value)
at ZipPackagePart.GetStreamCore(FileMode streamFileMode, FileAccess streamFileAccess)
at PackagePart.GetStream(FileMode mode, FileAccess access)
at PackagePart.GetStream(FileMode mode)
at XmlPartEditor.OpenDocumentForWrite()
at XpsPackagingPolicy.AcquireXmlWriterForFixedDocumentSequence()
at XpsSerializationManager.AcquireXmlWriter(Type writerType)
at DocumentSequenceSerializer.get_XmlWriter()
at DocumentSequenceSerializer.PersistObjectData(SerializableObjectContext serializableObjectContext)
at ReachSerializer.SerializeObject(Object serializedObject)
at XpsSerializationManager.SaveAsXaml(Object serializedObject)
at XpsDocumentWriter.SaveAsXaml(Object serializedObject, Boolean isSync)
at XpsDocumentWriter.Write(FixedDocumentSequence fixedDocumentSequence)

Expected behavior:
It should just create the XPS like in .NET Framework.

Minimal repro:
I've created a test project with a single test that shows the problem. The test succeeds on .NET Framework, but fails on .NET Core: https://github.com/thomasclaudiushuber/XpsNetCoreTests

@weltkante
Copy link

weltkante commented Jul 24, 2019

Related to #585 and PR #1311 - you may want to retry with nightly builds of preview8 - but I don't think your case is actually fixed yet, since the PR was mostly about reading streams, not writing them.

[edit] actually I think the PR #1311 is broken, because it wraps writing into a memory stream. While it may no longer throw it probably doesn't flush the writes to the original stream either.

@thomasclaudiushuber
Copy link
Contributor Author

@weltkante Thanks for linking. I've downloaded already the latest nightly build, but it's not fixed yet.

Yes, PR #1311 looks like it is fixing it. Let's see.

@weltkante
Copy link

weltkante commented Jul 24, 2019

@thomasclaudiushuber does this still throw in nightly preview8 or just drops data silently? If it still throws I may want to open a separate issue for revisiting PR #1311 because I think it doesn't handle wrapping writable streams correctly.

@thomasclaudiushuber
Copy link
Contributor Author

@weltkante I just tried it again. It throws exactly the same exception on preview8-013410. I've updated the preview version in the issue to that version.

@rladuca
Copy link
Member

rladuca commented Jul 24, 2019

I'll look at this in the context of the broader discussion about the seekability change.

From the testing we did on the backend, it looked like everything was fine with the passthrough, but perhaps we missed a scenario.

@rladuca
Copy link
Member

rladuca commented Jul 24, 2019

I just dipped into this and it looks like there are some parts of the code in ReachFramework that were missed when wrapping the GetStream functions in #1311 .

In light of @weltkante's comments I want to make 100% certain that these parts can use the same extensions without breaking.

@rladuca
Copy link
Member

rladuca commented Jul 25, 2019

Nothing in this repro goes through the extension functions as far as I can tell. This actually may be a bug within packaging.

>	System.IO.Compression.dll!System.IO.Compression.WrappedStream.ThrowIfCantSeek() Line 88	C#
 	System.IO.Compression.dll!System.IO.Compression.WrappedStream.SetLength(long value) Line 111	C#
 	System.IO.Packaging.dll!System.IO.Packaging.ZipWrappingStream.SetLength(long value) Line 76	C#
 	System.IO.Packaging.dll!System.IO.Packaging.ZipPackagePart.GetStreamCore(System.IO.FileMode streamFileMode, System.IO.FileAccess streamFileAccess) Line 34	C#
 	System.IO.Packaging.dll!System.IO.Packaging.PackagePart.GetStream(System.IO.FileMode mode, System.IO.FileAccess access) Line 323	C#
 	System.IO.Packaging.dll!System.IO.Packaging.PackagePart.GetStream(System.IO.FileMode mode) Line 292	C#
 	ReachFramework.dll!System.Windows.Xps.Packaging.XmlPartEditor.OpenDocumentForWrite() Line 259	C#

WPF is asking for a PackagePart to be opened FileMode.Create. ZipPackagePart eventually attempts to do the following specifically for FileMode.Create:
https://github.com/dotnet/corefx/blob/a10890f4ffe0fadf090c922578ba0e606ebdd16c/src/System.IO.Packaging/src/System/IO/Packaging/ZipPackagePart.cs#L30-L36

The call tempStream.SetLength(0) is what is causing this exception. The underlying stream isn't seekable, which ZipPackagePart is expecting. I don't yet know why this is the case, I have to take a deeper look to see if something WPF is doing prior to calling GetStream is the issue or if this is an actual bug with System.IO.Packaging or System.IO.Compression.

@rladuca
Copy link
Member

rladuca commented Jul 25, 2019

ZipArchiveEntry.GetDataCompressor created a new DeflateStream which is then wrapped, along with the original stream, by CheckSumAndSizeWriteStream.
https://github.com/dotnet/corefx/blob/78589e4d2c98bf71cefa4dbc94cde3783b60a934/src/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs#L600

CheckSumAndSizeWriteStream is never seekable and doesn't support SetPosition:
https://github.com/dotnet/corefx/blob/a10890f4ffe0fadf090c922578ba0e606ebdd16c/src/System.IO.Compression/src/System/IO/Compression/ZipCustomStreams.cs#L364

I don't see how WPF is influencing these calls, I'm going to write a repro without using WPF and see if I can cause the same problem to occur with a reasonable console app. If I can do that I will file a bug on CoreFX and convert this to tracking.

@rladuca rladuca self-assigned this Jul 25, 2019
@weltkante
Copy link

I'm wondering how the streams you were seeing in the existing extension method calls were ever seekable, weren't they coming from the same zip implementation? For what its worth writable streams not beeing seekable could be by design as well, because it allows streaming them through the compressor in a write-through way. If they were seekable they'd had to buffer everything and compress on Dispose.

@rladuca
Copy link
Member

rladuca commented Jul 25, 2019

Opening an existing document as ReadWrite gave me a seekable stream.

That's an entirely different path than Create. The ReadWrite path would open a deflate stream and read the entire stream into memory, basically what we were doing to wrap it.

https://github.com/dotnet/corefx/blob/78589e4d2c98bf71cefa4dbc94cde3783b60a934/src/System.IO.Compression/src/System/IO/Compression/ZipArchiveEntry.cs#L697

@rladuca
Copy link
Member

rladuca commented Jul 25, 2019

@rladuca rladuca added this to the 3.0 milestone Jul 25, 2019
@rladuca rladuca added Bug Product bug (most likely) rank20 Rank: Priority/rank on a scale of (1..100) labels Jul 25, 2019
@rladuca
Copy link
Member

rladuca commented Jul 25, 2019

Tagging as a bug for now, will switch to tracking if we can prove and file a bug on CoreFX.

@rladuca
Copy link
Member

rladuca commented Jul 25, 2019

I'm wondering how the streams you were seeing in the existing extension method calls were ever seekable, weren't they coming from the same zip implementation? For what its worth writable streams not beeing seekable could be by design as well, because it allows streaming them through the compressor in a write-through way. If they were seekable they'd had to buffer everything and compress on Dispose.

I am not sure this is truly by design, because they are assuming it is seekable by calling SetLength. That doesn't seem to make any sense to me. Anyway, haven't gotten around to reproducing it in a console app yet, if I can do that then it's definitely a bug since underlying stream implementations should not cause a bug via legitimate public API usage.

@rladuca
Copy link
Member

rladuca commented Jul 26, 2019

I was able to get a very simple repro in a console app:

 var zp = ZipPackage.Open("test.zip", System.IO.FileMode.Create, System.IO.FileAccess.Write);
 var part = zp.CreatePart(new System.Uri("/test.txt", UriKind.Relative), "");
 var stream = part.GetStream(System.IO.FileMode.Create);

This will follow the same stream creation path and throw NotSupportedException.

I'll file a bug on CoreFX and also see if I can get some workaround here.

@rladuca
Copy link
Member

rladuca commented Jul 26, 2019

Found a workaround.

Simply open the XpsDocument as FileAccess.ReadWrite. This is basically the same as the other workarounds for non-seekable streams.

This forces CoreFX to use the "update" path, which gives back a seekable stream.

@rladuca
Copy link
Member

rladuca commented Jul 26, 2019

Filed this bug on CoreFX: https://github.com/dotnet/corefx/issues/39816

Will convert this to tracking.

@rladuca rladuca added issue-type-tracking-external To track dependencies with other teams or repos and removed Bug Product bug (most likely) labels Jul 26, 2019
@stevenbrix
Copy link
Contributor

Simply open the XpsDocument as FileAccess.ReadWrite. This is basically the same as the other workarounds for non-seekable streams.

@ericstj is this by design? i remember in a few cases having to make similar changes as this to get seekability. Is there a matrix of all the different combinations of modes and the expected/supported functionality?

@grubioe grubioe assigned stevenbrix and unassigned rladuca Aug 14, 2019
@grubioe
Copy link
Contributor

grubioe commented Aug 14, 2019

Assigning to @stevenbrix as he is working on CoreFX bug.

@stevenbrix
Copy link
Contributor

The PR in dotnet/corefx is out: dotnet/corefx#40319

@wstaelens
Copy link
Contributor

Is this already solved? as we experience the same "NotSupportedException" on a server 2012r2 with XpsDocumentWriter.Write

@olowk
Copy link

olowk commented Oct 26, 2020

I don't think this is fixed yet, because the user here also complains about this issue:
#2609

@ghost ghost locked as resolved and limited conversation to collaborators Apr 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
issue-type-tracking-external To track dependencies with other teams or repos rank20 Rank: Priority/rank on a scale of (1..100)
Projects
None yet
Development

No branches or pull requests

7 participants