Summary
PR #1069 changed BufferResource::device_mr() to return an owning cuda::mr::any_resource<device_accessible> backed by OwningResourceAdaptor<RmmResourceAdaptor, std::shared_ptr<BufferResource>>. This ensures that any object storing the returned MR also keeps the owning BufferResource alive, including associated runtime state such as the stream pool.
To keep the PR scope manageable, host_mr(), pinned_mr(), and try_pinned_mr() were left unchanged and still return non-owning resources. This issue tracks extending the same ownership semantics to those accessors for consistency and lifetime safety.
HostMemoryResource and PinnedMemoryResource both depend on the owning BufferResource's stream pool for stream-ordered deallocation. As a result, the same lifetime hazard that motivated the device_mr() fix also exists for host and pinned allocations: a buffer allocated through one of these memory resources can outlive its owning BufferResource and later access destroyed runtime state during destruction.
In practice, this is currently unlikely to occur:
host_mr() has no external call sites in the codebase.
pinned_mr() has only two call sites.
try_pinned_mr() has six call sites, all in benign Statistics::report-style read-only paths.
So this issue is primarily about closing a latent lifetime gap and making the API behavior symmetric across all MR accessors, rather than fixing a known user-visible bug.
Proposed change
Make host_mr(), pinned_mr(), and try_pinned_mr() return owning memory resource handles that keep the parent BufferResource alive for as long as the returned MR exists, matching the semantics of device_mr().
This will likely reuse OwningResourceAdaptor in the same way as device_mr().
Summary
PR #1069 changed
BufferResource::device_mr()to return an owningcuda::mr::any_resource<device_accessible>backed byOwningResourceAdaptor<RmmResourceAdaptor, std::shared_ptr<BufferResource>>. This ensures that any object storing the returned MR also keeps the owningBufferResourcealive, including associated runtime state such as the stream pool.To keep the PR scope manageable,
host_mr(),pinned_mr(), andtry_pinned_mr()were left unchanged and still return non-owning resources. This issue tracks extending the same ownership semantics to those accessors for consistency and lifetime safety.HostMemoryResourceandPinnedMemoryResourceboth depend on the owningBufferResource's stream pool for stream-ordered deallocation. As a result, the same lifetime hazard that motivated thedevice_mr()fix also exists for host and pinned allocations: a buffer allocated through one of these memory resources can outlive its owningBufferResourceand later access destroyed runtime state during destruction.In practice, this is currently unlikely to occur:
host_mr()has no external call sites in the codebase.pinned_mr()has only two call sites.try_pinned_mr()has six call sites, all in benignStatistics::report-style read-only paths.So this issue is primarily about closing a latent lifetime gap and making the API behavior symmetric across all MR accessors, rather than fixing a known user-visible bug.
Proposed change
Make
host_mr(),pinned_mr(), andtry_pinned_mr()return owning memory resource handles that keep the parentBufferResourcealive for as long as the returned MR exists, matching the semantics ofdevice_mr().This will likely reuse
OwningResourceAdaptorin the same way asdevice_mr().