Skip to content

fix: ensure Python backend shm cleanup on forced shutdown - #450

Open
Vinya567 wants to merge 5 commits into
mainfrom
vinyak/fix-jetson-shm-shutdown-cleanup
Open

fix: ensure Python backend shm cleanup on forced shutdown#450
Vinya567 wants to merge 5 commits into
mainfrom
vinyak/fix-jetson-shm-shutdown-cleanup

Conversation

@Vinya567

@Vinya567 Vinya567 commented Jul 18, 2026

Copy link
Copy Markdown

What does the PR do?

Runtime fix for orphaned triton_python_backend_shm_region_* files when Python backend stub shutdown exceeds the server exit timeout. Pairs with the QA-side change in server#8881.

Ticket

Root cause

  • stub-timeout-seconds was parsed at backend init but not applied inside TerminateStub — the wait on the stub was effectively unbounded.
  • Parent-owned shm regions were only removed via the SharedMemoryManager destructor, so a forced/abnormal exit could skip cleanup and leak /dev/shm/triton_python_backend_shm_region_*.

Fix

  • Wire stub_timeout_seconds_ through StubLauncher::TerminateStub with a bounded pop + WaitForStubProcessWithTimeout; fall back to KillStubProcess on timeout (src/stub_launcher.{cc,h}).
  • Add explicit SharedMemoryManager::RemoveShmRegion() and call it from TerminateStub (src/shm_manager.{cc,h}).
  • Register parent-owned shm regions for std::atexit cleanup as a safety net for forced exits.

Test plan

  • IGX-Orin GitLab job 366443271: L0_backend_python--IGX-Orin lifecycle PASSED with this PR + server#8881; /dev/shm shm-region count unchanged before/after run.
  • x86: no regression on L0_backend_python/lifecycle.

Checklist

  • PR title reflects the change and is of format <type>: <description>
  • Changes are described in the pull request.
  • Related PRs are referenced.
  • Added test plan and verified test passes.

Commit Type

  • fix

Register parent-owned shm regions for atexit cleanup, remove regions
explicitly in TerminateStub, and honor stub-timeout-seconds during stub
teardown to avoid orphaned regions when server exit times out.
- Bump copyright to 2021-2026 on src/shm_manager.{cc,h}.
- Collapse wrapped stub_timeout_seconds_ assignment per clang-format.
@greptile-apps

greptile-apps Bot commented Jul 23, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes orphaned /dev/shm/triton_python_backend_shm_region_* files that leaked when Python stub shutdown exceeded the server exit timeout. It wires stub_timeout_seconds_ into TerminateStub with a shared budget across the finalize Pop and the process-wait, falling back to KillStubProcess on timeout, and adds an std::atexit safety net to unlink any registered regions if normal teardown is skipped.

  • shm_manager.{cc,h}: Adds RemoveShmRegion() (idempotent, sets delete_region_ = false) extracted from the destructor, plus file-scope RegisterParentShmRegion/UnregisterParentShmRegion helpers and a one-shot atexit handler that removes any still-live parent-owned regions.
  • stub_launcher.{cc,h}: Wires stub_timeout_seconds_ through both constructors (defaulting to 30 s) and Initialize(); replaces the unbounded Pop()/WaitForStubProcess() pair with a time-budgeted Pop(pop_timeout_ms, success) + WaitForStubProcessWithTimeout(remaining_seconds) + explicit shm_pool_->RemoveShmRegion() after the stub is dead; adds WaitForStubProcessWithTimeout with a final post-loop waitpid recheck to handle the process-exits-during-last-sleep edge case.

Confidence Score: 5/5

Safe to merge. The changes are well-scoped, handle edge cases correctly (zero remaining budget, final post-loop recheck, idempotent RemoveShmRegion), and the atexit lifetime ordering is sound.

The timeout budget sharing, the post-loop waitpid recheck, and the INT_MAX narrowing guard all address the previously raised concerns correctly. The atexit handler only touches pre-startup-initialized statics, so destruction order is safe. RemoveShmRegion() sets delete_region_=false on first call, making double-invocations (from TerminateStub and then the destructor) harmless. No new data races or resource-ordering issues were introduced.

Files Needing Attention: No files require special attention.

Important Files Changed

Filename Overview
src/stub_launcher.cc Core fix: wires stub_timeout_seconds_ into TerminateStub with a shared budget, adds WaitForStubProcessWithTimeout with a final post-loop recheck, and calls shm_pool_->RemoveShmRegion() unconditionally after stub death. All three prior review concerns (double-timeout, off-by-one, narrowing) are addressed.
src/stub_launcher.h Adds stub_timeout_seconds_ field (int64_t) and WaitForStubProcessWithTimeout declaration. Straightforward header update.
src/shm_manager.cc Extracts RemoveShmRegion() from the destructor for early idempotent cleanup, adds atexit safety net via file-scope register/unregister helpers. Logic is correct; atexit handler accesses only pre-startup-initialized statics so lifetime ordering is safe.
src/shm_manager.h Exposes RemoveShmRegion() as a public idempotent method with a clear doc comment. Clean header change.

Sequence Diagram

sequenceDiagram
    participant Server
    participant StubLauncher
    participant Stub
    participant ShmPool

    Server->>StubLauncher: TerminateStub()
    alt is_healthy
        StubLauncher->>Stub: Push(FinalizeRequest) via stub_message_queue
        Note over StubLauncher,Stub: Pop(pop_timeout_ms) — clamped to INT_MAX
        Stub-->>StubLauncher: "FinalizeResponse (or timeout → force_kill=true)"
        StubLauncher->>StubLauncher: reset queues / memory_manager
    else !is_healthy
        StubLauncher->>StubLauncher: "force_kill = true"
    end

    alt force_kill
        StubLauncher->>Stub: SIGKILL + waitpid (blocking)
    else WaitForStubProcessWithTimeout(remaining_seconds)
        loop "elapsed < timeout_seconds"
            StubLauncher->>Stub: waitpid(WNOHANG)
            Note over StubLauncher: sleep(1)
        end
        StubLauncher->>Stub: waitpid(WNOHANG) [final recheck]
        alt still alive
            StubLauncher->>Stub: KillStubProcess()
        end
    end

    StubLauncher->>ShmPool: RemoveShmRegion() [shm_unlink, idempotent]
    ShmPool->>ShmPool: UnregisterParentShmRegion() [remove from atexit set]
    StubLauncher->>StubLauncher: ipc_control_.reset() / queue resets

    Note over ShmPool: atexit safety net: removes any still-registered regions on exit()
Loading

Reviews (4): Last reviewed commit: "refactor: inline shm cleanup callback in..." | Re-trigger Greptile

Comment thread src/stub_launcher.cc Outdated
Comment thread src/stub_launcher.cc
Comment thread src/stub_launcher.cc Outdated
Vinya567 added 2 commits July 23, 2026 19:00
- Enforce stub_timeout_seconds_ as a single total budget across the
  finalize-wait and process-exit-wait phases; healthy teardown previously
  could take up to 2 * stub_timeout_seconds_.
- Clamp the Pop timeout to INT_MAX to avoid narrowing when passing int64_t
  into MessageQueue::Pop(int const&).
- Re-poll waitpid once after the final sleep window in
  WaitForStubProcessWithTimeout so a stub that exits during that second is
  not force-killed unnecessarily.
- Log a warning to stderr if std::atexit registration fails so the loss of
  the last-resort shm cleanup is visible; primary cleanup path is unaffected.
- Tighten inline comments to explain only intent/constraints, not mechanics.
@Vinya567
Vinya567 requested review from mc-nv, pskiran1 and yinggeh July 23, 2026 19:31
Comment thread src/shm_manager.cc Outdated
std::atomic<bool> parent_shm_atexit_registered{false};

void
CleanupParentShmRegions()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Consider merging CleanupParentShmRegions into RegisterParentShmRegion. It's used only by RegisterParentShmRegion.

@Vinya567 Vinya567 Aug 5, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good call done in c40d7cea.

CleanupParentShmRegions was only referenced as the std::atexit callback
inside RegisterParentShmRegion. Inline it as a capture-less lambda so the
teardown logic lives next to the registration and there's one fewer
top-level helper in the anonymous namespace.

No behavior change.
@Vinya567
Vinya567 requested a review from yinggeh August 5, 2026 20:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants