Skip to content

fix(dex-hand): release temp YAML config after optimizer build#479

Open
nvddr wants to merge 2 commits intomainfrom
fix/dex-hand-tempfile-leak
Open

fix(dex-hand): release temp YAML config after optimizer build#479
nvddr wants to merge 2 commits intomainfrom
fix/dex-hand-tempfile-leak

Conversation

@nvddr
Copy link
Copy Markdown
Contributor

@nvddr nvddr commented May 7, 2026

Summary

  • DexHandRetargeter._update_yaml writes a temp file (tempfile.mkstemp(suffix=".yml", prefix="dex_retarget_")) per construction so the URDF path can be patched without mutating the original config. The fd was closed but the file was never unlinked.
  • Track the temp path on the instance and unlink it right after RetargetingConfig.load_from_file(...).build() returns — the optimizer has parsed the YAML by then and no longer needs the file.
  • Add __del__ as a safety net for the construction path where the optimizer build raises after the temp file was written.
  • _cleanup_temp_config is idempotent (safe to call from both the explicit cleanup and __del__).

Why this matters

Long-running sessions, test suites, and pytest runs that instantiate many DexHandRetargeters leak a /tmp/dex_retarget_*.yml file each, slowly filling /tmp. No functional impact, but it's the kind of leak that surfaces as an outage on a long-running production deployment.

Test plan

  • Run any existing dex hand example/test; confirm /tmp/dex_retarget_* count is unchanged after the run vs. before.
  • CI retargeting suite green.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved temporary file cleanup to ensure all temporary configuration files are properly removed after optimizer initialization.
    • Added additional safety measures to guarantee cleanup completion even in edge cases.

DexHandRetargeter._update_yaml wrote a tempfile per construction (so the
URDF path could be patched without mutating the original config) and
never removed it. Long-running sessions or test suites that built many
retargeters left a stream of /tmp/dex_retarget_*.yml files behind.

Track the temp path on the instance and unlink it once
RetargetingConfig.load_from_file(...).build() has consumed the YAML.
__del__ acts as a safety net for cases where the optimizer build raises
between writing the temp file and the explicit cleanup.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 7, 2026 20:40
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 67d5d7b2-f003-4e0f-aadc-0db641e07597

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

DexHandRetargeter adds resource cleanup for temporary YAML config files generated during initialization. A new _temp_config_path instance field tracks the generated config path. The _prepare_configs() method now stores this path (or None if no temp file is created). A new _cleanup_temp_config() method safely deletes the tracked file and resets the field. The constructor explicitly calls cleanup after building the optimizer, and a __del__ destructor provides fallback cleanup on garbage collection to catch cases where explicit cleanup is not called.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title directly and clearly describes the main change: implementing cleanup of temporary YAML config files after optimizer build in DexHandRetargeter.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/dex-hand-tempfile-leak

Warning

Review ran into problems

🔥 Problems

Timed out fetching pipeline failures after 30000ms


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses a temporary-file leak in DexHandRetargeter by tracking the generated YAML config path and deleting the temp file once the dex_retargeting optimizer has been built.

Changes:

  • Delete the temp YAML config immediately after RetargetingConfig.load_from_file(...).build() completes.
  • Track the temp YAML path on the instance and add an idempotent cleanup helper.
  • Add a __del__ safety net to attempt cleanup if construction fails after writing the temp file.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/retargeters/dex_hand_retargeter.py Outdated
Comment on lines +314 to +319
if temp_config:
self._config.hand_retargeting_config = temp_config
# Track for cleanup once the optimizer has consumed the file.
self._temp_config_path: Optional[str] = temp_config
else:
self._temp_config_path = None
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/retargeters/dex_hand_retargeter.py`:
- Around line 314-333: _prepare_configs currently overwrites
self._config.hand_retargeting_config with a temp YAML path and
_cleanup_temp_config deletes that file but does not restore the original config,
leaving a stale path; change _prepare_configs to save the original value (e.g.,
self._original_hand_retargeting_config) before assigning
self._config.hand_retargeting_config = temp_config, and update
_cleanup_temp_config to restore self._config.hand_retargeting_config from
self._original_hand_retargeting_config (or set it to None if there was no
original), then remove the temp file and clear both self._temp_config_path and
self._original_hand_retargeting_config to avoid stale references.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 271c234e-8ab6-4694-a0a0-2ae20bef391f

📥 Commits

Reviewing files that changed from the base of the PR and between 260f766 and 8852275.

📒 Files selected for processing (1)
  • src/retargeters/dex_hand_retargeter.py

Comment thread src/retargeters/dex_hand_retargeter.py Outdated
Comment on lines +314 to +333
if temp_config:
self._config.hand_retargeting_config = temp_config
# Track for cleanup once the optimizer has consumed the file.
self._temp_config_path: Optional[str] = temp_config
else:
self._temp_config_path = None

def _cleanup_temp_config(self) -> None:
"""Remove the temp YAML written by ``_update_yaml`` once the optimizer
has been built from it. Safe to call repeatedly."""
path = getattr(self, "_temp_config_path", None)
if not path:
return
try:
os.unlink(path)
except FileNotFoundError:
pass
except OSError as e:
logger.warning(f"Failed to remove temp dex_retargeting config {path}: {e}")
self._temp_config_path = None
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

config.hand_retargeting_config is left pointing to a deleted file.

_prepare_configs() overwrites self._config.hand_retargeting_config with the temp YAML path, and _cleanup_temp_config() deletes that file. After construction, the config object now contains a stale path, so reusing the same DexHandRetargeterConfig can fail on the next initialization.

Suggested fix
@@
-        self._dex_hand = RetargetingConfig.load_from_file(
-            config.hand_retargeting_config
-        ).build()
+        self._dex_hand = RetargetingConfig.load_from_file(
+            self._retargeting_config_path
+        ).build()
@@
-        if temp_config:
-            self._config.hand_retargeting_config = temp_config
-            # Track for cleanup once the optimizer has consumed the file.
-            self._temp_config_path: Optional[str] = temp_config
-        else:
-            self._temp_config_path = None
+        # Keep caller-provided config immutable; use an internal load path.
+        self._retargeting_config_path = self._config.hand_retargeting_config
+        if temp_config:
+            self._retargeting_config_path = temp_config
+            # Track for cleanup once the optimizer has consumed the file.
+            self._temp_config_path: Optional[str] = temp_config
+        else:
+            self._temp_config_path = None
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/retargeters/dex_hand_retargeter.py` around lines 314 - 333,
_prepare_configs currently overwrites self._config.hand_retargeting_config with
a temp YAML path and _cleanup_temp_config deletes that file but does not restore
the original config, leaving a stale path; change _prepare_configs to save the
original value (e.g., self._original_hand_retargeting_config) before assigning
self._config.hand_retargeting_config = temp_config, and update
_cleanup_temp_config to restore self._config.hand_retargeting_config from
self._original_hand_retargeting_config (or set it to None if there was no
original), then remove the temp file and clear both self._temp_config_path and
self._original_hand_retargeting_config to avoid stale references.

CodeRabbit and Copilot flagged that _prepare_configs was overwriting
self._config.hand_retargeting_config with the temp YAML path; once
_cleanup_temp_config unlinks that file the config object now points at
a deleted path. Callers that reuse the same DexHandRetargeterConfig
would then fail to construct another retargeter.

Resolve the load path internally (self._retargeting_config_path) and
leave the caller's config untouched. The temp file is still tracked
separately for cleanup.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

2 participants