cudaipcclient: Protect IPC handle import/close with global lock

Protect import/close with signle lock to avoid importing a IPC handle
while it's being closed by another cudaipcsrc from other thread.
Also fixing cuda context leak

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5230>
This commit is contained in:
Seungha Yang 2023-08-23 19:17:57 +09:00 committed by GStreamer Marge Bot
parent 14c097e87d
commit 6fa405c1e2
2 changed files with 21 additions and 3 deletions

View file

@ -36,6 +36,7 @@ GST_DEBUG_CATEGORY (cuda_ipc_client_debug);
static GThreadPool *gc_thread_pool = nullptr; static GThreadPool *gc_thread_pool = nullptr;
/* *INDENT-OFF* */ /* *INDENT-OFF* */
static std::mutex gc_pool_lock; static std::mutex gc_pool_lock;
static std::recursive_mutex import_lock_;
/* *INDENT-ON* */ /* *INDENT-ON* */
void void
@ -88,9 +89,14 @@ struct GstCudaIpcHandle
~GstCudaIpcHandle () ~GstCudaIpcHandle ()
{ {
std::lock_guard <std::recursive_mutex> lk (import_lock_);
auto handle_dump = gst_cuda_ipc_mem_handle_to_string (handle);
GST_LOG ("Closing handle %s", handle_dump.c_str ());
gst_cuda_context_push (ctx); gst_cuda_context_push (ctx);
CuIpcCloseMemHandle (dptr); CuIpcCloseMemHandle (dptr);
gst_cuda_context_pop (nullptr); gst_cuda_context_pop (nullptr);
gst_object_unref (ctx);
GST_LOG ("Closed handle %s", handle_dump.c_str ());
} }
CUipcMemHandle handle; CUipcMemHandle handle;
@ -115,16 +121,17 @@ public:
std::shared_ptr<GstCudaIpcHandle> std::shared_ptr<GstCudaIpcHandle>
ImportHandle (CUipcMemHandle mem_handle, GstCudaContext * ctx) ImportHandle (CUipcMemHandle mem_handle, GstCudaContext * ctx)
{ {
std::lock_guard <std::mutex> lk (lock_); std::lock_guard <std::recursive_mutex> lk (import_lock_);
CUresult ret; CUresult ret;
CUdeviceptr dptr = 0; CUdeviceptr dptr = 0;
auto handle_dump = gst_cuda_ipc_mem_handle_to_string (mem_handle);
GST_LOG ("Trying to import handle %s", handle_dump.c_str ());
auto it = import_table_.begin (); auto it = import_table_.begin ();
while (it != import_table_.end ()) { while (it != import_table_.end ()) {
auto data = it->lock (); auto data = it->lock ();
if (!data) { if (!data) {
it = import_table_.erase (it); it = import_table_.erase (it);
} else if (gst_cuda_ipc_handle_is_equal (data->handle, mem_handle)) { } else if (gst_cuda_ipc_handle_is_equal (data->handle, mem_handle)) {
auto handle_dump = gst_cuda_ipc_mem_handle_to_string (mem_handle);
GST_LOG ("Returning already imported data %s", handle_dump.c_str ()); GST_LOG ("Returning already imported data %s", handle_dump.c_str ());
return data; return data;
} else { } else {
@ -143,6 +150,8 @@ public:
return nullptr; return nullptr;
} }
GST_LOG ("Imported handle %s", handle_dump.c_str ());
auto rst = std::make_shared<GstCudaIpcHandle> (mem_handle, dptr, ctx); auto rst = std::make_shared<GstCudaIpcHandle> (mem_handle, dptr, ctx);
import_table_.push_back (rst); import_table_.push_back (rst);
@ -151,7 +160,6 @@ public:
private: private:
std::vector<std::weak_ptr<GstCudaIpcHandle>> import_table_; std::vector<std::weak_ptr<GstCudaIpcHandle>> import_table_;
std::mutex lock_;
}; };
/* Global IPC handle table for legacy mode, since multiple CuIpcOpenMemHandle() /* Global IPC handle table for legacy mode, since multiple CuIpcOpenMemHandle()
@ -299,11 +307,15 @@ gst_cuda_ipc_client_set_flushing (GstCudaIpcClient * client, bool flushing)
priv = client->priv; priv = client->priv;
klass = GST_CUDA_IPC_CLIENT_GET_CLASS (client); klass = GST_CUDA_IPC_CLIENT_GET_CLASS (client);
GST_DEBUG_OBJECT (client, "Setting flush %d", flushing);
klass->set_flushing (client, flushing); klass->set_flushing (client, flushing);
std::lock_guard < std::mutex > lk (priv->lock); std::lock_guard < std::mutex > lk (priv->lock);
priv->flushing = flushing; priv->flushing = flushing;
priv->cond.notify_all (); priv->cond.notify_all ();
GST_DEBUG_OBJECT (client, "Setting flush %d done", flushing);
} }
static gpointer static gpointer
@ -566,7 +578,9 @@ gst_cuda_ipc_client_release_imported_data (GstCudaIpcReleaseData * data)
GST_LOG_OBJECT (self, "Releasing data %s", handle_dump.c_str ()); GST_LOG_OBJECT (self, "Releasing data %s", handle_dump.c_str ());
import_lock_.lock ();
data->imported = nullptr; data->imported = nullptr;
import_lock_.unlock ();
priv->lock.lock (); priv->lock.lock ();
priv->unused_data.push (handle); priv->unused_data.push (handle);

View file

@ -390,6 +390,8 @@ gst_cuda_ipc_src_unlock (GstBaseSrc * src)
if (priv->client) if (priv->client)
gst_cuda_ipc_client_set_flushing (priv->client, true); gst_cuda_ipc_client_set_flushing (priv->client, true);
GST_DEBUG_OBJECT (self, "Unlocked");
return TRUE; return TRUE;
} }
@ -406,6 +408,8 @@ gst_cuda_ipc_src_unlock_stop (GstBaseSrc * src)
if (priv->client) if (priv->client)
gst_cuda_ipc_client_set_flushing (priv->client, false); gst_cuda_ipc_client_set_flushing (priv->client, false);
GST_DEBUG_OBJECT (self, "Unlock stopped");
return TRUE; return TRUE;
} }