nvcodec: fix invalidated std::set::iterator usage

As per the C++ standard, any usage of a std::set::iterator after it has
been erased from the collection results in undefined behaviour. This has
resulted in application crashes due to CUDA illegal address errors.

This commit fixes the issue by copying and incrementing the iterator
within any for-loops that also invoke std::set::erase.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8472>
This commit is contained in:
James Oliver 2025-02-13 10:04:16 +08:00 committed by GStreamer Marge Bot
parent ae47dd2529
commit bd37947254
2 changed files with 15 additions and 12 deletions

View File

@ -453,12 +453,13 @@ gst_cuda_ipc_server_on_release_data (GstCudaIpcServer * self,
GST_LOG_OBJECT (self, "RELEASE-DATA %s, conn-id: %u",
handle_dump.c_str (), conn->id);
for (auto it = conn->peer_handles.begin (); it != conn->peer_handles.end ();
it++) {
CUipcMemHandle & tmp = (*it)->handle;
for (auto it = conn->peer_handles.begin ();
it != conn->peer_handles.end ();) {
auto current = it++;
CUipcMemHandle & tmp = (*current)->handle;
if (gst_cuda_ipc_handle_is_equal (tmp, handle)) {
found = true;
conn->peer_handles.erase (it);
conn->peer_handles.erase (current);
break;
}
}
@ -480,11 +481,12 @@ gst_cuda_ipc_server_on_release_data (GstCudaIpcServer * self,
GST_LOG_OBJECT (self, "RELEASE-MMAP-DATA %" GST_CUDA_OS_HANDLE_FORMAT
", conn-id %u", handle, conn->id);
for (auto it = conn->peer_handles.begin (); it != conn->peer_handles.end ();
it++) {
if ((*it)->os_handle == handle) {
for (auto it = conn->peer_handles.begin ();
it != conn->peer_handles.end ();) {
auto current = it++;
if ((*current)->os_handle == handle) {
found = true;
conn->peer_handles.erase (it);
conn->peer_handles.erase (current);
break;
}
}

View File

@ -690,10 +690,11 @@ GstNvEncObject::runResourceGC ()
GST_LOG_ID (id_.c_str (), "Running resource GC");
DeviceLock ();
for (auto it : resource_queue_) {
if (active_resource_queue_.find (it) == active_resource_queue_.end ()) {
releaseResourceUnlocked (it);
resource_queue_.erase (it);
for (auto it = resource_queue_.begin(); it != resource_queue_.end();) {
auto current = it++;
if (active_resource_queue_.find (*current) == active_resource_queue_.end ()) {
releaseResourceUnlocked (*current);
resource_queue_.erase (*current);
}
}
DeviceUnlock ();