Python API: edge neighborhood nodes retain visitors after leaving scope

Open
#2,542 1 comment 0 reactions 1 assignee View on GitHub

Maintainers usually reply within 1 day

@klayoutmatthias is already working on this.

Since Nov 10, 2026.

  • #2543 by @klayoutmatthias — open

Assessment

This issue has not been assessed yet.

Description

bug

Creating CompoundRegionOperationNode.new_edge_neighborhood leaves its Python visitor alive after the node wrapper and all Python references to the visitor have been dropped. Repeated construction accumulates visitors and any data attached to them. Calling Region.complex_op is not needed to reproduce this.

Expected: once the node and visitor are no longer referenced, the visitor can be collected.

Minimal reproduction:

import gc
import weakref
from typing import List, Tuple
import klayout.db as kdb

class Visitor(kdb.EdgeNeighborhoodVisitor):
    def on_edge(self, layout: kdb.Layout, cell: kdb.Cell, edge: kdb.Edge, neighborhood: List):
        pass

def make() -> Tuple[weakref.ReferenceType, weakref.ReferenceType]:
    visitor = Visitor()
    node = kdb.CompoundRegionOperationNode.new_edge_neighborhood(
        children=[], visitor=visitor)
    return weakref.ref(visitor), weakref.ref(node)

references = [make() for _ in range(100)]
gc.collect()
print("Visitors alive:", sum(visitor() is not None for visitor, _ in references))
print("Node wrappers alive:", sum(node() is not None for _, node in references))

Actual: 100 visitors and zero node wrappers remain alive.

Controls:

  • Constructing and discarding visitors without constructing nodes leaves zero of 100 visitors alive
  • Creating nodes without executing them leaves 1, 10 and 100 visitors alive after 1, 10 and 100 calls
  • Executing complex_op on ordinary flat rectangular regions gives the same 1, 10 and 100 counts
  • The node-only and flat-region reproductions also retain all 100 visitors on Linux with Python 3.12.3

The reproduction has no extraction context, DeepShapeStore, callback instrumentation or retained strong-reference collection. Its observation list contains only weak references.

This is distinct from #2495, which concerned retained on_edge arguments and was fixed by #2501. Here no callback needs to run. In KPEX, each visitor refers to the extraction results, so retained visitors can keep completed extraction data alive when operations are repeated in one process.

The v0.30.13 source appears consistent with this lifetime observation:

Versions:

  • KLayout Python module 0.30.13, Python 3.14.6, macOS 26.6.2
  • Independent node-only and flat-region reproductions: KLayout Python module 0.30.13, Python 3.12.3, Linux
  • The KLayout executable is not involved
  • Source tag v0.30.13, commit 06b8ff4909ad1696c06c634183d8fd0eaa8a1b83
Dominant language
C++
Stars
1.2k
Forks
305
Avg merge
3d 2h
Merged PRs (30d)
11

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from KLayout/klayout

All issues in KLayout/klayout

Similar issues

More C++ issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.