Skip to content

Close the Newton viewer before dropping the reference to it - #7590

Draft
fatimaanes wants to merge 1 commit into
isaac-sim:developfrom
fatimaanes:fix/newton-visualizer-viewer-teardown
Draft

Close the Newton viewer before dropping the reference to it#7590
fatimaanes wants to merge 1 commit into
isaac-sim:developfrom
fatimaanes:fix/newton-visualizer-viewer-teardown

Conversation

@fatimaanes

Copy link
Copy Markdown
Collaborator

Description

NewtonVisualizer dropped its viewer without closing it in two paths:

  • normal shutdown through close()
  • the step() recovery path that disables the viewer after an initialization failure

This left OVRTX resources to be released by the garbage collector in an undefined order. If the renderer was destroyed before its active bindings and retained step results, shutdown could report:

Renderer destroyed with 1 active binding(s)
OV RTX: Leaking step result outputs

Both paths now use a shared _release_viewer() helper that calls viewer.close() before clearing the reference.

During normal shutdown, teardown failures continue to propagate after the remaining cleanup completes. If viewer cleanup also fails in the step() recovery path, the error is logged without interrupting training.

Type of change

  • Bug fix (non-breaking)

Release backport

  • Backport this pull request to the active release branch after it merges into develop

The same issue is present on release/3.0.0.

Validation

Controlled teardown reproduction

The controlled test reproduced the reported shutdown signature:

Version Active-binding warnings Leaked-step-result errors
Without fix 1 2
With fix 0 0

Windows — RTX PRO 6000

Ran each of the two reported workloads three times, for six runs per batch:

Version Completed Active-binding warnings Leaked-step-result errors New warnings
Without fix 6/6 1/6 0/6
With fix 6/6 0/6 0/6 0

The OVRTX window failed to initialize on this machine, so every run exercised the step() recovery path. A pre-existing USD asset-loading crash occurred once in each batch before viewer initialization and is being tracked separately.

Linux — L40

The nine new regression tests fail against the original implementation and pass with the fix:

Version Visualizer test results
Without fix 58 passed, 9 failed
With fix 67 passed, 0 failed

Seven tests requiring the full Isaac Sim runtime were excluded because of a pre-existing collection error.

Checklist

  • I have read and understood the contribution guidelines
  • I have run the pre-commit checks with ./isaaclab.sh --format
  • I have made corresponding changes to the documentation — not applicable
  • My changes generate no new warnings
  • I have added tests that prove the fix is effective
  • I have added the required changelog fragment under source/<pkg>/changelog.d/
  • My name is already included in CONTRIBUTORS.md

NewtonVisualizer gave up its viewer in two places -- close() and the step()
handler that permanently disables the viewer after an unrecoverable failure --
by assigning self._viewer = None without calling viewer.close() first.

ViewerRTX.close() releases GPU resources in a fixed order: it waits on the
in-flight render, drops the retained step results, unbinds the transform
AttributeBinding and only then releases the ovrtx.Renderer. Skipping it leaves
all four objects to the garbage collector, which guarantees no order. When the
collector reaches the Renderer first it tears itself down with the binding and
step results still live, warning "Renderer destroyed with 1 active binding(s)"
and logging "Leaking step result outputs" once per retained render product.

Route both paths through a single _release_viewer() helper that closes the
viewer and clears the reference in a finally block, so an unusable viewer is
never retained while the teardown failure still reaches the caller.

The two callers need different error handling. close() lets the failure
propagate -- SimulationContext._update_visualizers() already wraps it -- but
runs its own remaining cleanup in a finally block so a failing viewer cannot
strand the generated camera prims or leave _is_closed unset. The step() handler
contains the failure, because that handler exists so an unusable viewer
disables itself instead of aborting training; letting a teardown error escape
would replace the original failure and crash the run it was written to save.

ViewerBase.close() is a no-op, so the GL, null and file backends are
unaffected. The viser and rerun visualizers already close their viewers.

The _Viewer double in test_newton_adapter.py gains the close() method that
every real viewer inherits from ViewerBase; without it the double no longer
models the viewers it stands in for.
@github-actions github-actions Bot added bug Something isn't working isaac-lab Related to Isaac Lab team labels Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working isaac-lab Related to Isaac Lab team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant