Skip to content

fix(install): add trap handler to spin() for clean Ctrl+C teardown#1070

Merged
kjw3 merged 3 commits intoNVIDIA:mainfrom
latenighthackathon:fix/install-spin-trap-handler
Mar 30, 2026
Merged

fix(install): add trap handler to spin() for clean Ctrl+C teardown#1070
kjw3 merged 3 commits intoNVIDIA:mainfrom
latenighthackathon:fix/install-spin-trap-handler

Conversation

@latenighthackathon
Copy link
Copy Markdown
Contributor

@latenighthackathon latenighthackathon commented Mar 29, 2026

Summary

spin() runs background commands with a spinner but had no signal handler. Ctrl+C during installation orphaned the background process and leaked temp files. Added INT/TERM trap and global EXIT trap for defense-in-depth.

Related Issue

Closes #1020

Changes

  • Added INT/TERM trap inside spin() that kills background PID and cleans temp file
  • Added global _cleanup_pids/_cleanup_files arrays with EXIT trap
  • spin() registers/deregisters from global arrays on entry/completion
  • trap - restores defaults after normal process exit

Type of Change

  • Code change for a new feature, bug fix, or refactor.
  • Code change with doc updates.
  • Doc only. Prose changes without code sample modifications.
  • Doc only. Includes code sample changes.

Testing

  • npx prek run --all-files passes (or equivalently make check).
  • npm test passes.
  • make docs builds without warnings. (for doc-only changes)

Checklist

General

Code Changes

  • Formatters applied.
  • No secrets, API keys, or credentials committed.

Summary by CodeRabbit

  • Chores
    • Installation script now reliably tracks and cleans up background processes and temporary files on exit and interruptions, reducing leftover artifacts and improving installer robustness and failure handling.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 29, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a10a480b-efa0-4d41-b2b9-d5ac082ceb91

📥 Commits

Reviewing files that changed from the base of the PR and between 587cb94 and b7443c9.

📒 Files selected for processing (1)
  • install.sh
✅ Files skipped from review due to trivial changes (1)
  • install.sh

📝 Walkthrough

Walkthrough

Global cleanup and signal handling were added to install.sh: arrays track background PIDs and temp log files and a _global_cleanup function is registered via trap for EXIT; spin() now records/unrecords entries, installs a temporary INT/TERM handler to kill the spinner and remove its temp log (exit 130), then restores handling after the background job finishes.

Changes

Cohort / File(s) Summary
Global cleanup & traps
install.sh
Added _cleanup_pids and _cleanup_files arrays and a _global_cleanup function registered via trap _global_cleanup EXIT to kill tracked background PIDs and remove tracked temp files on exit.
spin() behavior
install.sh
Updated spin() to append spinner PID and temp log to global lists, install a temporary INT/TERM trap that kills the spinner, removes its temp log and exits 130, then restore default signal handling and remove the handled PID/log from the global lists after wait.

Sequence Diagram(s)

sequenceDiagram
    participant User as "User (Ctrl+C)"
    participant OS as "OS"
    participant Script as "install.sh"
    participant Job as "Background Job\n(e.g., npm, git, docker)"

    rect rgba(100,149,237,0.5)
    User->>OS: SIGINT / SIGTERM
    OS->>Script: deliver signal (trap)
    end

    rect rgba(60,179,113,0.5)
    Script->>Script: _global_cleanup (trap handler)
    Script->>Job: kill background PID(s)
    Script->>Script: rm -f temp log files
    Script->>OS: exit
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I twirled a tiny spinner bright,
Till Ctrl+C leapt into the night.
I nipped each orphan, swept the log,
Hopped home happy through the fog—
Now installs sleep tidy and light. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding a trap handler to spin() for clean Ctrl+C teardown, which directly addresses the PR's core objective.
Linked Issues check ✅ Passed The PR implementation meets all coding requirements from issue #1020: global cleanup arrays, INT/TERM trap in spin(), global EXIT trap, and proper deregistration after cleanup.
Out of Scope Changes check ✅ Passed All changes in install.sh are directly scoped to implementing trap handlers and cleanup tracking as required by issue #1020; no extraneous modifications detected.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

Copy link
Copy Markdown
Contributor

@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.

🧹 Nitpick comments (1)
install.sh (1)

197-238: Consider a global EXIT trap for more robust cleanup (optional).

The current function-scoped trap handles the primary use case well. For additional robustness, the linked issue (#1020) suggested maintaining global arrays (_cleanup_pids, _cleanup_files) with an EXIT trap to catch all exit paths. This would protect against edge cases like set -e triggering between trap clearance and explicit cleanup.

Given the sequential nature of spin() calls in this script and the small risk window, the current approach is reasonable. The global pattern could be considered if future changes introduce more complex cleanup needs.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@install.sh` around lines 197 - 238, The spin() function currently installs a
temporary INT/TERM trap and removes the temp file on completion, but to make
cleanup robust for all exit paths (e.g., set -e or unexpected exits) add global
cleanup arrays and a single EXIT trap: create global arrays _cleanup_pids and
_cleanup_files and an initialization that registers a one-time trap on EXIT
which iterates those arrays to kill remaining PIDs and remove files; inside
spin() push the background pid onto _cleanup_pids and the mktemp path onto
_cleanup_files, and on normal completion remove those entries from the arrays
before clearing the per-function trap; ensure symbols referenced are spin,
_cleanup_pids, _cleanup_files and the global EXIT trap so temp logs are always
removed and background processes killed even if the script exits unexpectedly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@install.sh`:
- Around line 197-238: The spin() function currently installs a temporary
INT/TERM trap and removes the temp file on completion, but to make cleanup
robust for all exit paths (e.g., set -e or unexpected exits) add global cleanup
arrays and a single EXIT trap: create global arrays _cleanup_pids and
_cleanup_files and an initialization that registers a one-time trap on EXIT
which iterates those arrays to kill remaining PIDs and remove files; inside
spin() push the background pid onto _cleanup_pids and the mktemp path onto
_cleanup_files, and on normal completion remove those entries from the arrays
before clearing the per-function trap; ensure symbols referenced are spin,
_cleanup_pids, _cleanup_files and the global EXIT trap so temp logs are always
removed and background processes killed even if the script exits unexpectedly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5e63824b-8d6a-444d-979d-3bfef958bc4f

📥 Commits

Reviewing files that changed from the base of the PR and between eb4ba8c and 37eb660.

📒 Files selected for processing (1)
  • install.sh

@kjw3
Copy link
Copy Markdown
Contributor

kjw3 commented Mar 29, 2026

@latenighthackathon all your commits need to have verified signatures. Please fix on this PR and any other PRs you put up against NemoClaw

@latenighthackathon
Copy link
Copy Markdown
Contributor Author

@kjw3 - fixed TY!

spin() runs commands in the background with a spinner animation but
had no signal handler. Pressing Ctrl+C during installation would
kill the parent shell while leaving the background process running
and the temp log file on disk.

Add INT/TERM trap inside spin() that kills the background process
and removes the temp file, then restore default signal handling
after the background process exits normally.

Closes NVIDIA#1020
The function-scoped INT/TERM trap in spin() handles Ctrl+C well, but
set -e triggering between trap clearance and explicit rm -f could
leak temp files or orphan background processes.

Add global _cleanup_pids and _cleanup_files arrays with an EXIT trap
that catches all exit paths. spin() registers its PID and temp file
on entry and deregisters on normal completion. This defense-in-depth
ensures cleanup even on unexpected exits.

Addresses CodeRabbit review suggestion.
@latenighthackathon latenighthackathon force-pushed the fix/install-spin-trap-handler branch from f715321 to 587cb94 Compare March 29, 2026 22:12
Copy link
Copy Markdown
Contributor

@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 the current code and only fix it if needed.

Inline comments:
In `@install.sh`:
- Around line 248-250: The removals of $pid and $log from the global cleanup
arrays (_cleanup_pids and _cleanup_files) are happening before the actual
cleanup (rm -f and any pid termination) and risk leaking resources if a signal
arrives; move the two lines that dereference
_cleanup_pids=("${_cleanup_pids[@]/$pid/}") and
_cleanup_files=("${_cleanup_files[@]/$log/}") so they execute only after the
corresponding cleanup actions (e.g., after rm -f "$log" and after the pid
termination/cleanup code) have completed; ensure the deregistration happens
immediately after the actual removal/kill so the EXIT trap still knows about the
resource until it is gone.
🪄 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: Pro

Run ID: 4cbac186-9b69-4466-bf21-7485a46d3f69

📥 Commits

Reviewing files that changed from the base of the PR and between bc85d09 and 587cb94.

📒 Files selected for processing (1)
  • install.sh

Move _cleanup_pids and _cleanup_files deregistration to after the
actual cleanup actions (rm -f, pid termination) so the global EXIT
trap still covers these resources if a signal arrives mid-cleanup.

Closes CodeRabbit review comment on NVIDIA#1070.

Signed-off-by: latenighthackathon <latenighthackathon@users.noreply.github.com>
@kjw3 kjw3 self-assigned this Mar 30, 2026
@kjw3 kjw3 merged commit a146385 into NVIDIA:main Mar 30, 2026
8 of 9 checks passed
@latenighthackathon
Copy link
Copy Markdown
Contributor Author

Thanks to @stevenobiajulu who also tackled this in #1026 — appreciate the parallel effort on the install cleanup. Great to see multiple contributors independently identifying the same reliability gap.

@latenighthackathon latenighthackathon deleted the fix/install-spin-trap-handler branch March 30, 2026 19:47
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.

[NemoClaw] install.sh spin() has no trap handler — Ctrl+C orphans background processes and leaks temp files

2 participants