Skip to content

Commit 699501e

Browse files
Copilotbrianrobleculver
authored
Fix unhandled ArgumentOutOfRangeException when exporting FlameGraph with unrendered canvas (#2339)
Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: brianrob <[email protected]> Co-authored-by: leculver <[email protected]>
1 parent 8e9a5be commit 699501e

File tree

3 files changed

+57
-4
lines changed

3 files changed

+57
-4
lines changed

src/PerfView.Tests/StackViewer/StackWindowTests.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,5 +859,39 @@ public override string GetFrameName(StackSourceFrameIndex frameIndex, bool verbo
859859
return frameIndex.ToString();
860860
}
861861
}
862+
863+
[WpfFact]
864+
[WorkItem(2308, "https://github.com/Microsoft/perfview/issues/2308")]
865+
public void TestExportFlameGraphWithInvalidCanvasSize()
866+
{
867+
// Create a canvas with zero size (simulating an unrendered or collapsed canvas)
868+
var canvas = new Canvas();
869+
canvas.Width = 0;
870+
canvas.Height = 0;
871+
canvas.Measure(new Size(0, 0));
872+
canvas.Arrange(new Rect(0, 0, 0, 0));
873+
874+
var tempFile = Path.GetTempFileName();
875+
try
876+
{
877+
// Attempt to export should throw ArgumentOutOfRangeException with a meaningful message
878+
var exception = Assert.Throws<ArgumentOutOfRangeException>(() =>
879+
{
880+
FlameGraph.Export(canvas, tempFile);
881+
});
882+
883+
// Verify the exception message is helpful
884+
Assert.Contains("Canvas has an invalid size", exception.Message);
885+
Assert.Contains("width=0", exception.Message);
886+
Assert.Contains("height=0", exception.Message);
887+
}
888+
finally
889+
{
890+
if (File.Exists(tempFile))
891+
{
892+
File.Delete(tempFile);
893+
}
894+
}
895+
}
862896
}
863897
}

src/PerfView/StackViewer/FlameGraph.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,18 @@ public static IEnumerable<FlameBox> Calculate(CallTree callTree, double maxWidth
8383
public static void Export(Canvas flameGraphCanvas, string filePath)
8484
{
8585
var rectangle = new Rect(flameGraphCanvas.RenderSize);
86-
var renderTargetBitmap = new RenderTargetBitmap((int)rectangle.Right, (int)rectangle.Bottom, 96d, 96d, PixelFormats.Default);
86+
int width = (int)rectangle.Right;
87+
int height = (int)rectangle.Bottom;
88+
89+
// Validate that the canvas has a valid size before attempting to export
90+
if (width <= 0 || height <= 0)
91+
{
92+
throw new ArgumentOutOfRangeException(
93+
nameof(flameGraphCanvas),
94+
$"Canvas has an invalid size (width={width}, height={height}). Please ensure the flame graph is visible and has been rendered before attempting to export.");
95+
}
96+
97+
var renderTargetBitmap = new RenderTargetBitmap(width, height, 96d, 96d, PixelFormats.Default);
8798
renderTargetBitmap.Render(flameGraphCanvas);
8899

89100
var pngEncoder = new PngBitmapEncoder();

src/PerfView/StackViewer/StackWindow.xaml.cs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2764,10 +2764,18 @@ private void DoSaveFlameGraph(object sender, RoutedEventArgs e)
27642764
var result = saveDialog.ShowDialog();
27652765
if (result == true)
27662766
{
2767-
if (FlameGraphCanvas.IsEmpty || m_RedrawFlameGraphWhenItBecomesVisible)
2768-
RedrawFlameGraph();
2767+
try
2768+
{
2769+
if (FlameGraphCanvas.IsEmpty || m_RedrawFlameGraphWhenItBecomesVisible)
2770+
RedrawFlameGraph();
27692771

2770-
FlameGraph.Export(FlameGraphCanvas, saveDialog.FileName);
2772+
FlameGraph.Export(FlameGraphCanvas, saveDialog.FileName);
2773+
StatusBar.Log($"Saved flame graph to {saveDialog.FileName}");
2774+
}
2775+
catch (ArgumentOutOfRangeException ex)
2776+
{
2777+
StatusBar.LogError($"Failed to save flame graph: {ex.Message}");
2778+
}
27712779
}
27722780
}
27732781

0 commit comments

Comments
 (0)