fix: ensure Python backend shm cleanup on forced shutdown - #450
Conversation
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 SummaryThis PR fixes orphaned
Confidence Score: 5/5Safe 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
Sequence DiagramsequenceDiagram
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()
Reviews (4): Last reviewed commit: "refactor: inline shm cleanup callback in..." | Re-trigger Greptile |
- 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.
| std::atomic<bool> parent_shm_atexit_registered{false}; | ||
|
|
||
| void | ||
| CleanupParentShmRegions() |
There was a problem hiding this comment.
Consider merging CleanupParentShmRegions into RegisterParentShmRegion. It's used only by RegisterParentShmRegion.
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.
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 inserver#8881.Ticket
Root cause
stub-timeout-secondswas parsed at backend init but not applied insideTerminateStub— the wait on the stub was effectively unbounded.SharedMemoryManagerdestructor, so a forced/abnormal exit could skip cleanup and leak/dev/shm/triton_python_backend_shm_region_*.Fix
stub_timeout_seconds_throughStubLauncher::TerminateStubwith a bounded pop +WaitForStubProcessWithTimeout; fall back toKillStubProcesson timeout (src/stub_launcher.{cc,h}).SharedMemoryManager::RemoveShmRegion()and call it fromTerminateStub(src/shm_manager.{cc,h}).std::atexitcleanup as a safety net for forced exits.Test plan
L0_backend_python--IGX-Orinlifecycle PASSED with this PR +server#8881;/dev/shmshm-region count unchanged before/after run.L0_backend_python/lifecycle.Checklist
<type>: <description>Commit Type