Conversation
ProcessUserModelReadinessRequest declared error_string_shm inside the has_exception block, so the unique_ptr freed the Boost shm allocation before the stub notified the parent. Parent LoadFromSharedMemory then touched a freed handle, corrupting the pool free-list and hanging the stub (~98% CPU) on is_ready() exception / non-boolean paths. Widen error_string_shm to function scope so it survives notify -> parent Load -> ack, matching GetCUDAMemoryPoolAddress in the same file. Fixes triton-inference-server/server#8978 Signed-off-by: Dundy Pasupuleti <dundysm@gmail.com>
|
@dyastremsky @pskiran1 @Kanupriyagoyal @mc-nv @BhaskarVenkatesha reviewing / ack welcome. fix is the scope widen described in the pr body; l0 model_readiness left to ci. |
|
| // Keep error_string_shm alive until after parent ack so the parent can | ||
| // LoadFromSharedMemory the handle before this function returns and frees it. | ||
| // Same lifetime pattern as GetCUDAMemoryPoolAddress above. | ||
| std::unique_ptr<PbString> error_string_shm; |
There was a problem hiding this comment.
Error string can expire early If the parent sees the readiness response but is delayed for more than five seconds before loading its error string, the stub’s acknowledgement wait times out and destroys
error_string_shm. The parent can then load a freed shared-memory handle, leaving the use-after-free possible despite this change.
Knowledge Base Used: Python stub process and IPC
|
Hi @dundysm, Thank you for your interest in this issue and for taking the time to put this PR together. I reported #8978 and already have a fix in progress on my side. It is currently going through our internal review before I submit it upstream. In your comment on the issue you mentioned you would stand down if I preferred to take it, and I would like to take you up on that. Could you please close this PR? I will be opening a PR for this fix myself in the next few days and will link it to #8978 so everyone following can track it. Thanks again for your understanding and for helping move this forward. |
What does the PR do?
fixes a use-after-free in
Stub::ProcessUserModelReadinessRequestthat permanently hangs the python backend stub (and often the server shm pool) when useris_ready()raises or returns a non-boolean.Ticket / issue
Root cause
on the
has_exceptionpath,error_string_shmwas declared inside theif (has_exception)block. its destructor runs at the closing brace, which frees the Boost managed shm allocation (ref_count_1 -> 0 ->DeallocateUnsafe) before the stub notifies the parent.the parent then does
PbString::LoadFromSharedMemory(pool, readiness_payload->error)on an already-freed handle, which corrupts the pool free-list. the next deallocate can spin holding the single pool mutex (~98% cpu on the stub); laterIPCMessage::Createblocks on the same mutex. hang is permanent for that model instance.success paths (
is_readytrue/false) never allocate an error string, so they never hit this. only:test_is_ready_raises_exceptiontest_is_ready_returns_non_booleantake the broken path. matches the reporter repro 100%.
Fix
widen
std::unique_ptr<PbString> error_string_shmto function scope so it survives notify -> parent Load -> ack. same lifetime pattern already used byGetCUDAMemoryPoolAddressin this file (which explicitly comments that the wait exists so the parent can finish reading before the function returns and frees that shm).handshake, timeout (
kUserModelReadinessTimeoutMs), and parentRunUserModelReadinessCheckLoad/ack path are unchanged. sticky-error caching is out of scope.rebuild note: this change is in
pb_stub.cc, which builds intotriton_python_backend_stubonly (notlibtriton_python.so). shipping a fixed.sowithout a rebuilt stub leaves the bug live.Test plan
src/pb_stub.cc(done). full stub cmake build +qa/L0_backend_python/model_readiness/test.shneeds a Triton server tree / QA image; not run in this environment. please rely on CI / L0 for the hang repro.qa/L0_backend_python/model_readiness/test_is_ready_raises_exceptionandtest_is_ready_returns_non_booleanshould complete (assert NOT READY, then healthy model still READY) with no pegged stub cpu and no indefinite hangtest_is_ready_returns_true/returns_false/ coroutine / timeout / concurrent as regressionChecklist
<type>: <description>Commit Type
cc @dyastremsky @pskiran1 @Kanupriyagoyal @mc-nv @BhaskarVenkatesha