Repository navigation
[Win32] Release a region's previous area when it is refilled - #3768
Merged
HeikoKlare merged 1 commit intoOct 30, 2026
Merged
HeikoKlare merged 1 commit into
HeikoKlare merged 1 commit into
Conversation
Contributor
HeikoKlare
force-pushed
the
win32-region-set-release-previous-operations
branch
from
October 28, 2026 11:43
3c65e4d to
b818e67
Compare
There was a problem hiding this comment.
🔵 Needs a closer look
The lifetime change depends on unmerged PR #3769, whose reference-counting fix is absent from this snapshot, and requires Windows validation of combined-region reuse and the GDI-handle regression.
No open issues 🎉
What changed in this PR
Prevents GDI handle accumulation on Windows when GC.getClipping(Region) repeatedly replaces a region’s area. This change depends on #3769 to keep shared operations alive and must merge after it.
Changes:
- Releases and clears operations describing the region’s previous area before storing its replacement.
- Adds a regression test that refills one region 15,000 times and verifies its bounds.
| File | Description |
|---|---|
bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Region.java |
Releases previous area operations when replacing a region’s contents. |
bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/graphics/RegionWin32Tests.java |
Tests repeated clipping retrieval without exhausting GDI handles. |
Review effort: Balanced
HeikoKlare
marked this pull request as ready for review
October 28, 2026 13:01
r-mennig
approved these changes
Oct 29, 2026
r-mennig
left a comment
Contributor
There was a problem hiding this comment.
The change looks sound to me and fixes the stated resource leak. Thanks for this fix!
A Region describes its area by a list of operations that is replayed to create a native region handle per zoom level. GC.getClipping(Region) fills a region by appending an operation that owns one GDI region handle per zoom, but the operations describing the region's previous area were never released although they are replaced. As a result, every call of GC.getClipping on a region that is filled repeatedly retained one more operation and one more GDI region handle, none of them freed before the region was disposed. The common idiom of a paint listener that keeps a single Region field and fills it on every paint therefore exhausted the per-process GDI object quota after a few thousand paints, after which handle creation started to fail and unrelated code ran out of handles. Replaying the ever growing operation list also made queries like contains or getBounds progressively slower. Such a region now only retains the operations describing its current area, so its resource consumption stays constant no matter how often it is refilled. The operations are reference counted, so releasing a region's previous area drops only that region's own reference: a snapshot taken elsewhere, such as the copy GC.setClipping keeps, holds a reference of its own. Assisted-by: Claude Opus 5 <noreply@anthropic.com>
HeikoKlare
force-pushed
the
win32-region-set-release-previous-operations
branch
from
October 30, 2026 11:11
b818e67 to
4bcc63d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On Windows,
GC.getClipping(Region)fills a region by appending an operation that owns a GDI region handle, but it never releases the operations describing the region's previous area, although that area is replaced.Filling the same region repeatedly, as a paint listener with a single
Regionfield does, therefore leaks one GDI handle per call until the region is disposed, and runs into the per-process limit of 10000 GDI objects after a few thousand paints.Relates to #3763.
Solution
A region that is filled now releases its previous area, so its resource consumption stays constant no matter how often it is refilled.
Merge order
Depends on #3769 and should land after it. Until that fix is in, releasing the previous area while the region is still alive can pull the ground from under a region it was combined into: combining a region filled by
GC.getClippinginto another region and then refilling the first one makes the second one fail with aNoSuchElementException.🤖 Generated with Claude Code