Fix crashes from OOM in vkDestroyInstance

Various situations could cause an OOM to turn into a hard crash due to double freeing
of memory that was improperly cleaned up. Also fixed memory leaks when layers would
report OOM.
This commit is contained in:
Charles Giessen
2022-05-27 16:36:35 -06:00
committed by Charles Giessen
parent 4f6ccc2f2f
commit c129609717
6 changed files with 175 additions and 19 deletions
+89 -2
View File
@@ -355,6 +355,14 @@ TEST(Allocation, DeviceButNotInstance) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
const char* layer_name = "VkLayerImplicit0";
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name(layer_name)
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DISABLE_ENV")),
"test_layer.json");
env.get_test_layer().set_do_spurious_allocations_in_create_instance(true).set_do_spurious_allocations_in_create_device(true);
MemoryTracker tracker;
{
auto& driver = env.get_test_icd();
@@ -403,6 +411,14 @@ TEST(Allocation, CreateInstanceIntentionalAllocFail) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
const char* layer_name = "VkLayerImplicit0";
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name(layer_name)
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DISABLE_ENV")),
"test_layer.json");
env.get_test_layer().set_do_spurious_allocations_in_create_instance(true).set_do_spurious_allocations_in_create_device(true);
size_t fail_index = 0;
VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY;
while (result == VK_ERROR_OUT_OF_HOST_MEMORY && fail_index <= 10000) {
@@ -433,6 +449,14 @@ TEST(Allocation, CreateDeviceIntentionalAllocFail) {
driver.physical_devices.emplace_back("physical_device_1");
driver.physical_devices[1].add_queue_family_properties({{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, false});
const char* layer_name = "VkLayerImplicit0";
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name(layer_name)
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DISABLE_ENV")),
"test_layer.json");
env.get_test_layer().set_do_spurious_allocations_in_create_instance(true).set_do_spurious_allocations_in_create_device(true);
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
@@ -488,6 +512,14 @@ TEST(Allocation, CreateInstanceDeviceIntentionalAllocFail) {
driver.physical_devices.emplace_back("physical_device_0");
driver.physical_devices[0].add_queue_family_properties({{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, false});
const char* layer_name = "VkLayerImplicit0";
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name(layer_name)
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DISABLE_ENV")),
"test_layer.json");
env.get_test_layer().set_do_spurious_allocations_in_create_instance(true).set_do_spurious_allocations_in_create_device(true);
size_t fail_index = 0;
VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY;
while (result == VK_ERROR_OUT_OF_HOST_MEMORY && fail_index <= 10000) {
@@ -556,6 +588,15 @@ TEST(TryLoadWrongBinaries, CreateInstanceIntentionalAllocFail) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
env.add_icd(TestICDDetails(CURRENT_PLATFORM_DUMMY_BINARY_WRONG_TYPE).set_is_fake(true));
const char* layer_name = "VkLayerImplicit0";
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name(layer_name)
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DISABLE_ENV")),
"test_layer.json");
env.get_test_layer().set_do_spurious_allocations_in_create_instance(true).set_do_spurious_allocations_in_create_device(true);
size_t fail_index = 0;
VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY;
while (result == VK_ERROR_OUT_OF_HOST_MEMORY && fail_index <= 10000) {
@@ -579,6 +620,14 @@ TEST(Allocation, EnumeratePhysicalDevicesIntentionalAllocFail) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
const char* layer_name = "VkLayerImplicit0";
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name(layer_name)
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DISABLE_ENV")),
"test_layer.json");
env.get_test_layer().set_do_spurious_allocations_in_create_instance(true).set_do_spurious_allocations_in_create_device(true);
size_t fail_index = 0;
bool reached_the_end = false;
uint32_t starting_physical_dev_count = 3;
@@ -612,6 +661,7 @@ TEST(Allocation, EnumeratePhysicalDevicesIntentionalAllocFail) {
for (uint32_t i = 0; i < 2; i++) {
driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(physical_dev_count));
driver.physical_devices.back().add_queue_family_properties({{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, false});
physical_dev_count += 1;
}
@@ -639,7 +689,33 @@ TEST(Allocation, EnumeratePhysicalDevicesIntentionalAllocFail) {
}
ASSERT_EQ(physical_dev_count, returned_physical_count);
std::cout << "fail count " << fail_index << "\n";
std::array<VkDevice, 3> devices;
for (uint32_t i = 0; i < returned_physical_count; i++) {
uint32_t family_count = 1;
uint32_t returned_family_count = 0;
env.vulkan_functions.vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[i], &returned_family_count, nullptr);
ASSERT_EQ(returned_family_count, family_count);
VkQueueFamilyProperties family;
env.vulkan_functions.vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[i], &returned_family_count, &family);
ASSERT_EQ(returned_family_count, family_count);
ASSERT_EQ(family.queueFlags, static_cast<VkQueueFlags>(VK_QUEUE_GRAPHICS_BIT));
ASSERT_EQ(family.queueCount, family_count);
ASSERT_EQ(family.timestampValidBits, 0U);
DeviceCreateInfo dev_create_info;
DeviceQueueCreateInfo queue_info;
queue_info.add_priority(0.0f);
dev_create_info.add_device_queue(queue_info);
result = env.vulkan_functions.vkCreateDevice(physical_devices[i], dev_create_info.get(), tracker.get(), &devices[i]);
}
for (uint32_t i = 0; i < returned_physical_count; i++) {
if (result == VK_SUCCESS) {
env.vulkan_functions.vkDestroyDevice(devices[i], tracker.get());
}
}
env.vulkan_functions.vkDestroyInstance(instance, tracker.get());
ASSERT_TRUE(tracker.empty());
reached_the_end = true;
@@ -659,6 +735,14 @@ TEST(Allocation, CreateInstanceDeviceWithDXGIDriverIntentionalAllocFail) {
driver.physical_devices[0].add_queue_family_properties({{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, false});
}
const char* layer_name = "VkLayerImplicit0";
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name(layer_name)
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DISABLE_ENV")),
"test_layer.json");
env.get_test_layer().set_do_spurious_allocations_in_create_instance(true).set_do_spurious_allocations_in_create_device(true);
auto& known_driver = known_driver_list.at(2); // which drive this test pretends to be
DXGI_ADAPTER_DESC1 desc1{};
desc1.VendorId = known_driver.vendor_id;
@@ -721,9 +805,12 @@ TEST(Allocation, CreateInstanceDeviceWithDXGIDriverIntentionalAllocFail) {
dev_create_info.add_device_queue(queue_info);
result = env.vulkan_functions.vkCreateDevice(physical_devices[i], dev_create_info.get(), tracker.get(), &devices[i]);
if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
devices[i] = VK_NULL_HANDLE;
}
}
for (uint32_t i = 0; i < returned_physical_count; i++) {
if (result == VK_SUCCESS) {
if (devices[i] != VK_NULL_HANDLE) {
env.vulkan_functions.vkDestroyDevice(devices[i], tracker.get());
}
}