Skip to content

Commit 8a81c82

Browse files
committed
[CTS] Fix resource leaks
This patch introduces the `uur::raii::Wrapper<T>` object and per handle aliases (`uur::raii::Context` for `ur_context_handle_t` etc.) to replace instances of the following pattern in test bodies: ```cpp TEST(Context, Example) { ur_context_handle_t context = nullptr; ASSERT_SUCCESS(urContextCreate(1, &device, nullptr, &context)); // potential resource leak as `ASSERT_*` returns from this function ASSERT_TRUE(might_be_false); urContextRelease(context); } ``` With the following: ```cpp TEST(Context, Example) { uur::raii::Context context = nullptr; ASSERT_SUCCESS(urContextCreate(1, &device, nullptr, context.ptr())); // no leak because the destructor releases the context ASSERT_TRUE(might_be_false); } ```
1 parent 96cc58d commit 8a81c82

18 files changed

+355
-276
lines changed

test/adapters/cuda/context_tests.cpp

Lines changed: 51 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "context.hpp"
77
#include "fixtures.h"
88
#include "queue.hpp"
9+
#include "uur/raii.h"
910
#include <thread>
1011

1112
using cudaUrContextCreateTest = uur::urDeviceTest;
@@ -14,14 +15,13 @@ UUR_INSTANTIATE_DEVICE_TEST_SUITE_P(cudaUrContextCreateTest);
1415
constexpr unsigned int known_cuda_api_version = 3020;
1516

1617
TEST_P(cudaUrContextCreateTest, CreateWithChildThread) {
17-
18-
ur_context_handle_t context = nullptr;
19-
ASSERT_SUCCESS(urContextCreate(1, &device, nullptr, &context));
18+
uur::raii::Context context = nullptr;
19+
ASSERT_SUCCESS(urContextCreate(1, &device, nullptr, context.ptr()));
2020
ASSERT_NE(context, nullptr);
2121

2222
// Retrieve the CUDA context to check information is correct
2323
auto checkValue = [=] {
24-
CUcontext cudaContext = context->get();
24+
CUcontext cudaContext = context.handle->get();
2525
unsigned int version = 0;
2626
EXPECT_SUCCESS_CUDA(cuCtxGetApiVersion(cudaContext, &version));
2727
EXPECT_EQ(version, known_cuda_api_version);
@@ -39,27 +39,26 @@ TEST_P(cudaUrContextCreateTest, CreateWithChildThread) {
3939

4040
auto callContextFromOtherThread = std::thread(checkValue);
4141
callContextFromOtherThread.join();
42-
ASSERT_SUCCESS(urContextRelease(context));
4342
}
4443

4544
TEST_P(cudaUrContextCreateTest, ActiveContext) {
46-
ur_context_handle_t context = nullptr;
47-
ASSERT_SUCCESS(urContextCreate(1, &device, nullptr, &context));
45+
uur::raii::Context context = nullptr;
46+
ASSERT_SUCCESS(urContextCreate(1, &device, nullptr, context.ptr()));
4847
ASSERT_NE(context, nullptr);
4948

50-
ur_queue_handle_t queue = nullptr;
49+
uur::raii::Queue queue = nullptr;
5150
ur_queue_properties_t queue_props{UR_STRUCTURE_TYPE_QUEUE_PROPERTIES,
5251
nullptr, 0};
53-
ASSERT_SUCCESS(urQueueCreate(context, device, &queue_props, &queue));
52+
ASSERT_SUCCESS(urQueueCreate(context, device, &queue_props, queue.ptr()));
5453
ASSERT_NE(queue, nullptr);
5554

5655
// check that the queue has the correct context
5756
ASSERT_EQ(context, queue->getContext());
5857

5958
// create a buffer
60-
ur_mem_handle_t buffer = nullptr;
59+
uur::raii::Mem buffer = nullptr;
6160
ASSERT_SUCCESS(urMemBufferCreate(context, UR_MEM_FLAG_READ_WRITE, 1024,
62-
nullptr, &buffer));
61+
nullptr, buffer.ptr()));
6362
ASSERT_NE(buffer, nullptr);
6463

6564
// check that the context is now the active CUDA context
@@ -71,11 +70,6 @@ TEST_P(cudaUrContextCreateTest, ActiveContext) {
7170
ASSERT_SUCCESS(urContextGetNativeHandle(context, &native_context));
7271
ASSERT_NE(native_context, nullptr);
7372
ASSERT_EQ(cudaCtx, reinterpret_cast<CUcontext>(native_context));
74-
75-
// release resources
76-
ASSERT_SUCCESS(urMemRelease(buffer));
77-
ASSERT_SUCCESS(urQueueRelease(queue));
78-
ASSERT_SUCCESS(urContextRelease(context));
7973
}
8074

8175
TEST_P(cudaUrContextCreateTest, ContextLifetimeExisting) {
@@ -89,13 +83,13 @@ TEST_P(cudaUrContextCreateTest, ContextLifetimeExisting) {
8983
ASSERT_EQ(original, current);
9084

9185
// create a UR context
92-
ur_context_handle_t context;
93-
ASSERT_SUCCESS(urContextCreate(1, &device, nullptr, &context));
86+
uur::raii::Context context;
87+
ASSERT_SUCCESS(urContextCreate(1, &device, nullptr, context.ptr()));
9488
ASSERT_NE(context, nullptr);
9589

9690
// create a queue with the context
97-
ur_queue_handle_t queue;
98-
ASSERT_SUCCESS(urQueueCreate(context, device, nullptr, &queue));
91+
uur::raii::Queue queue;
92+
ASSERT_SUCCESS(urQueueCreate(context, device, nullptr, queue.ptr()));
9993
ASSERT_NE(queue, nullptr);
10094

10195
// ensure the queue has the correct context
@@ -109,19 +103,16 @@ TEST_P(cudaUrContextCreateTest, ContextLifetimeExisting) {
109103
// check that context is now the active cuda context
110104
ASSERT_SUCCESS_CUDA(cuCtxGetCurrent(&current));
111105
ASSERT_EQ(current, context->get());
112-
113-
ASSERT_SUCCESS(urQueueRelease(queue));
114-
ASSERT_SUCCESS(urContextRelease(context));
115106
}
116107

117108
TEST_P(cudaUrContextCreateTest, ThreadedContext) {
118109
// create two new UR contexts
119-
ur_context_handle_t context1;
120-
ASSERT_SUCCESS(urContextCreate(1, &device, nullptr, &context1));
110+
uur::raii::Context context1;
111+
ASSERT_SUCCESS(urContextCreate(1, &device, nullptr, context1.ptr()));
121112
ASSERT_NE(context1, nullptr);
122113

123-
ur_context_handle_t context2;
124-
ASSERT_SUCCESS(urContextCreate(1, &device, nullptr, &context2));
114+
uur::raii::Context context2;
115+
ASSERT_SUCCESS(urContextCreate(1, &device, nullptr, context2.ptr()));
125116
ASSERT_NE(context2, nullptr);
126117

127118
// setup synchronization variables between the main thread and
@@ -138,23 +129,22 @@ TEST_P(cudaUrContextCreateTest, ThreadedContext) {
138129
auto test_thread = std::thread([&] {
139130
CUcontext current = nullptr;
140131

141-
// create a queue with the first context
142-
ur_queue_handle_t queue;
143-
ASSERT_SUCCESS(urQueueCreate(context1, device, nullptr, &queue));
144-
ASSERT_NE(queue, nullptr);
145-
146-
// ensure that the queue has the correct context
147-
ASSERT_EQ(context1, queue->getContext());
132+
{
133+
// create a queue with the first context
134+
uur::raii::Queue queue;
135+
ASSERT_SUCCESS(
136+
urQueueCreate(context1, device, nullptr, queue.ptr()));
137+
ASSERT_NE(queue, nullptr);
148138

149-
// create a buffer to set context1 as the active context
150-
ur_mem_handle_t buffer;
151-
ASSERT_SUCCESS(urMemBufferCreate(context1, UR_MEM_FLAG_READ_WRITE, 1024,
152-
nullptr, &buffer));
153-
ASSERT_NE(buffer, nullptr);
139+
// ensure that the queue has the correct context
140+
ASSERT_EQ(context1, queue->getContext());
154141

155-
// release the mem and queue
156-
ASSERT_SUCCESS(urMemRelease(buffer));
157-
ASSERT_SUCCESS(urQueueRelease(queue));
142+
// create a buffer to set context1 as the active context
143+
uur::raii::Mem buffer;
144+
ASSERT_SUCCESS(urMemBufferCreate(context1, UR_MEM_FLAG_READ_WRITE,
145+
1024, nullptr, buffer.ptr()));
146+
ASSERT_NE(buffer, nullptr);
147+
}
158148

159149
// mark the first set of processing as done and notify the main thread
160150
std::unique_lock<std::mutex> lock(m);
@@ -166,31 +156,31 @@ TEST_P(cudaUrContextCreateTest, ThreadedContext) {
166156
lock.lock();
167157
cv.wait(lock, [&] { return released; });
168158

169-
// create a queue with the 2nd context
170-
ASSERT_SUCCESS(urQueueCreate(context2, device, nullptr, &queue));
171-
ASSERT_NE(queue, nullptr);
172-
173-
// ensure queue has correct context
174-
ASSERT_EQ(context2, queue->getContext());
175-
176-
// create a buffer to set the active context
177-
ASSERT_SUCCESS(urMemBufferCreate(context2, UR_MEM_FLAG_READ_WRITE, 1024,
178-
nullptr, &buffer));
179-
180-
// check that the 2nd context is now tha active cuda context
181-
ASSERT_SUCCESS_CUDA(cuCtxGetCurrent(&current));
182-
ASSERT_EQ(current, context2->get());
183-
184-
// release
185-
ASSERT_SUCCESS(urMemRelease(buffer));
186-
ASSERT_SUCCESS(urQueueRelease(queue));
159+
{
160+
// create a queue with the 2nd context
161+
uur::raii::Queue queue = nullptr;
162+
ASSERT_SUCCESS(
163+
urQueueCreate(context2, device, nullptr, queue.ptr()));
164+
ASSERT_NE(queue, nullptr);
165+
166+
// ensure queue has correct context
167+
ASSERT_EQ(context2, queue->getContext());
168+
169+
// create a buffer to set the active context
170+
uur::raii::Mem buffer = nullptr;
171+
ASSERT_SUCCESS(urMemBufferCreate(context2, UR_MEM_FLAG_READ_WRITE,
172+
1024, nullptr, buffer.ptr()));
173+
174+
// check that the 2nd context is now tha active cuda context
175+
ASSERT_SUCCESS_CUDA(cuCtxGetCurrent(&current));
176+
ASSERT_EQ(current, context2->get());
177+
}
187178
});
188179

189180
// wait for the thread to be done with the first queue to release the first
190181
// context
191182
std::unique_lock<std::mutex> lock(m);
192183
cv.wait(lock, [&] { return thread_done; });
193-
ASSERT_SUCCESS(urContextRelease(context1));
194184

195185
// notify the other thread that the context was released
196186
released = true;
@@ -199,6 +189,4 @@ TEST_P(cudaUrContextCreateTest, ThreadedContext) {
199189

200190
// wait for the thread to finish
201191
test_thread.join();
202-
203-
ASSERT_SUCCESS(urContextRelease(context2));
204192
}

0 commit comments

Comments
 (0)