Skip to content

Fix GDAL dataset leak in RasterLayer::loadAndReprojectFile (#96)#114

Merged
rolker merged 11 commits into
jazzyfrom
feature/issue-96
Jun 22, 2026
Merged

Fix GDAL dataset leak in RasterLayer::loadAndReprojectFile (#96)#114
rolker merged 11 commits into
jazzyfrom
feature/issue-96

Conversation

@rolker

@rolker rolker commented Jun 22, 2026

Copy link
Copy Markdown
Owner

Closes #96

Summary

RasterLayer::loadAndReprojectFile opened two GDAL datasets (GDALOpen source + GDALAutoCreateWarpedVRT warped VRT) and never closed either — leaking both on every return path (normal, the !reprojected_dataset early return that leaked the source, and the abort-flag return {} paths). Triggered by the RasterLayer ctor, setColormap(), and readSettings(), so flipping a colormap ramp leaked two handles per flip.

Fix

  • RAII — both handles wrapped in std::unique_ptr<GDALDataset, …> with a GDALClose deleter, so all return/abort paths free both automatically (mirrors the sibling initExtent()).
  • Close order preserveddataset declared before reprojected_dataset, so reverse-declaration destruction closes the warped VRT first, source second (the VRT references the source); a comment records the constraint.

Test

New test/test_raster_layer_gdal_cleanup.cpp: writes a synthetic 8×8 WGS84 Float32 GeoTIFF, constructs a RasterLayer, flips the colormap twice (each re-invokes loadAndReprojectFile), destroys the layer, and asserts the process-wide open-dataset count returns to its pre-construction baseline (delta == 0). The test asserts each load actually reached the warp path (via status()), so it can't pass vacuously — verified by a neutered-deleter check producing delta == 6.

102 tests, 0 failures (2 pre-existing GL-gated skips).

Scope note

This is a real, bounded leak (load / colormap-change), not the cause of the #98 zoom/pan OOM — RasterLayer has no viewport handler and reprojects once, so zoom/pan doesn't re-invoke this path. #98's OOM is MapTiles tile accumulation, tracked separately.


Authored-By: Claude Code Agent
Model: Claude Opus 4.8

Claude Code Agent added 11 commits June 22, 2026 01:57
RAII unique_ptr fix for both GDAL handles in loadAndReprojectFile + regression test via GDALDataset::GetOpenDatasets
loadAndReprojectFile opened a source dataset (GDALOpen) and a warped VRT
(GDALAutoCreateWarpedVRT) and closed neither, leaking both on every return
path — normal return, the !reprojected_dataset early return (leaked the
source), and the abort-flag return {} paths (leaked both). Triggered on every
RasterLayer ctor, setColormap(), and readSettings().

Wrap both handles in std::unique_ptr with a GDALClose deleter so all paths
free them automatically. dataset stays declared before reprojected_dataset so
reverse-declaration destruction closes the warped VRT first, then the source
(the VRT references the source) — matching initExtent(); a comment records the
ordering constraint.
Add test_raster_layer_gdal_cleanup: write a synthetic WGS84 single-band
Float32 GeoTIFF, construct a RasterLayer, flip the colormap twice (each
re-invokes loadAndReprojectFile), destroy the layer, and assert the
process-wide open-dataset count returns to its pre-construction baseline.

Baseline-delta rather than == 0, since GDALDataset::GetOpenDatasets() counts
all process-wide handles. Guards against a vacuous pass by asserting each load
actually reached the warp path and succeeded (status() == "") — a load that
never warps never opens the handles under test. Verified the test fails when
the RAII close is removed.

Also sync plan.md with the as-built fix (three folded Plan Review
resolutions; open questions resolved).
Copilot AI review requested due to automatic review settings June 22, 2026 04:40

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@rolker rolker merged commit e78dc57 into jazzy Jun 22, 2026
1 check failed
@rolker rolker deleted the feature/issue-96 branch June 22, 2026 04:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RasterLayer::loadAndReprojectFile leaks GDAL datasets (no GDALClose)

2 participants