Sporadic AccessViolationException when UseEnvironmentFonts is false and documents are generated in parallel
ebarnard opened this issue · comments
Describe the bug
We have a suite of snapshot comparison tests for the QuestPDF components we use in our reports.
These complete without error when UseEnvironmentFonts
is true
, or when not run in parallel, but when it is false
a test will eventually fail with an AccessViolationException.
Parallel | Not Parallel | |
---|---|---|
UseEnvironmentFonts = true |
Ok | Ok |
UseEnvironmentFonts = false |
Exception | Ok |
This was not an issue prior to version 2024.3.0.
To Reproduce
I don't yet have a small reproducer but am working on it. I'm filing this issue now in case there is a known or obvious fix.
Expected behavior
Document generation succeeds without throwing an AccessViolationException
.
Environment
QuestPDF 2024.3.1
Windows 10 x64
Stack trace
The active test run was aborted. Reason: Test host process crashed : Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Repeat 2 times:
--------------------------------
at QuestPDF.Skia.Text.SkParagraph+API.paragraph_plan_layout(IntPtr, Single)
--------------------------------
at QuestPDF.Skia.Text.SkParagraph.PlanLayout(Single)
at QuestPDF.Elements.Text.TextBlock.CalculateParagraphMetrics(QuestPDF.Infrastructure.Size)
at QuestPDF.Elements.Text.TextBlock.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Drawing.Proxy.CacheProxy.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Elements.Padding.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Drawing.Proxy.CacheProxy.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Elements.Padding.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Elements.Table.Table+<>c__DisplayClass52_0.<PlanLayout>g__GetRenderingCommands|1()
at QuestPDF.Elements.Table.Table.PlanLayout(QuestPDF.Infrastructure.Size)
at QuestPDF.Elements.Table.Table.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Drawing.Proxy.CacheProxy.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Elements.Decoration.<PlanLayout>g__GetDecorationMeasurement|20_0(QuestPDF.Infrastructure.Element, <>c__DisplayClass20_0 ByRef)
at QuestPDF.Elements.Decoration+<PlanLayout>d__20.MoveNext()
at System.Collections.Generic.List`1[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]..ctor(System.Collections.Generic.IEnumerable`1<System.__Canon>)
at System.Linq.Enumerable.ToList[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Collections.Generic.IEnumerable`1<System.__Canon>)
at QuestPDF.Elements.Decoration.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Drawing.Proxy.CacheProxy.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Elements.EnsureSpace.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Drawing.Proxy.CacheProxy.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Elements.Padding.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Drawing.Proxy.CacheProxy.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Elements.Column.PlanLayout(QuestPDF.Infrastructure.Size)
at QuestPDF.Elements.Column.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Drawing.Proxy.CacheProxy.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Elements.Extend.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Drawing.Proxy.CacheProxy.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Elements.Extend.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Drawing.Proxy.CacheProxy.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Elements.Decoration+<PlanLayout>d__20.MoveNext()
at System.Collections.Generic.List`1[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]..ctor(System.Collections.Generic.IEnumerable`1<System.__Canon>)
at System.Linq.Enumerable.ToList[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Collections.Generic.IEnumerable`1<System.__Canon>)
at QuestPDF.Elements.Decoration.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Drawing.Proxy.CacheProxy.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Elements.Padding.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Drawing.Proxy.CacheProxy.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Elements.Constrained.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Elements.Layers.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Infrastructure.ContainerElement.Measure(QuestPDF.Infrastructure.Size)
at QuestPDF.Drawing.DocumentGenerator.RenderPass[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](QuestPDF.Infrastructure.PageContext, System.__Canon, QuestPDF.Infrastructure.ContainerElement)
at QuestPDF.Drawing.DocumentGenerator.RenderSingleDocument[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.__Canon, QuestPDF.Infrastructure.IDocument, QuestPDF.Infrastructure.DocumentSettings)
at QuestPDF.Drawing.DocumentGenerator.RenderDocument[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.__C
Thank you for reaching out 😄
I have investigated this problem and found a root cause. Your findings have helped me a lot, so thank you for sharing so many details! I don't expect any performance degradation after the fix.
Would you please test the newest 2024.3.2 version? https://github.com/QuestPDF/QuestPDF/releases/tag/2024.3.2
I've run the test suite in parallel a few times using 2024.3.2 and haven't got a single AccessViolationException so I think it's fixed.
Thank you so much for sorting this out quickly.