From 3acd6b3e9cd4c828c199c2d5c1502b3ee9296554 Mon Sep 17 00:00:00 2001 From: Rafal Rudnicki Date: Fri, 10 Apr 2026 12:07:38 +0000 Subject: [PATCH] fix memory provider cleanup on initialization failures --- src/memory_provider.c | 12 +++++++- test/memoryProviderAPI.cpp | 61 +++++++++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/src/memory_provider.c b/src/memory_provider.c index 413de848fc..24fff20c0c 100644 --- a/src/memory_provider.c +++ b/src/memory_provider.c @@ -1,6 +1,6 @@ /* * - * Copyright (C) 2023-2025 Intel Corporation + * Copyright (C) 2023-2026 Intel Corporation * * Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception @@ -360,6 +360,11 @@ umf_result_t umfMemoryProviderCreate(const umf_memory_provider_ops_t *ops, ret = provider->ops.get_name(provider->provider_priv, &pname); if (ret != UMF_RESULT_SUCCESS) { LOG_ERR("Failed to get pool name"); + umf_result_t finalize_ret = + provider->ops.finalize(provider->provider_priv); + if (finalize_ret != UMF_RESULT_SUCCESS) { + LOG_ERR("Failed to finalize provider after create failure"); + } umf_ba_global_free(provider); return ret; } @@ -373,6 +378,11 @@ umf_result_t umfMemoryProviderCreate(const umf_memory_provider_ops_t *ops, ret = umfProviderPostInitialize(&provider->ops, provider_priv); if (ret != UMF_RESULT_SUCCESS && ret != UMF_RESULT_ERROR_INVALID_CTL_PATH) { LOG_ERR("Failed to post-initialize provider"); + umf_result_t finalize_ret = + provider->ops.finalize(provider->provider_priv); + if (finalize_ret != UMF_RESULT_SUCCESS) { + LOG_ERR("Failed to finalize provider after create failure"); + } umf_ba_global_free(provider); return ret; } diff --git a/test/memoryProviderAPI.cpp b/test/memoryProviderAPI.cpp index 5cbc8c2cac..f88ed59ecd 100644 --- a/test/memoryProviderAPI.cpp +++ b/test/memoryProviderAPI.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2023-2025 Intel Corporation +// Copyright (C) 2023-2026 Intel Corporation // Under the Apache License v2.0 with LLVM Exceptions. See LICENSE.TXT. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // This file contains tests for UMF provider API @@ -363,6 +363,65 @@ TEST_P(providerInitializeTest, errorPropagation) { ASSERT_EQ(ret, this->GetParam()); } +static int *provider_destroy_count_ptr = nullptr; + +TEST_F(test, memoryProviderCreateCleansUpWhenGetNameFails) { + int provider_destroy_count = 0; + + struct provider_fail_get_name : public umf_test::provider_base_t { + ~provider_fail_get_name() override { (*provider_destroy_count_ptr)++; } + + umf_result_t get_name(const char **) noexcept { + return UMF_RESULT_ERROR_UNKNOWN; + } + }; + + provider_destroy_count_ptr = &provider_destroy_count; + + umf_memory_provider_ops_t provider_ops = + umf_test::providerMakeCOps(); + + umf_memory_provider_handle_t hProvider = nullptr; + auto ret = umfMemoryProviderCreate(&provider_ops, nullptr, &hProvider); + + ASSERT_EQ(ret, UMF_RESULT_ERROR_UNKNOWN); + ASSERT_EQ(hProvider, nullptr); + ASSERT_EQ(provider_destroy_count, 1); + provider_destroy_count_ptr = nullptr; +} + +TEST_F(test, memoryProviderCreateCleansUpWhenPostInitializeFails) { + int provider_destroy_count = 0; + + struct provider_fail_post_initialize : public umf_test::provider_base_t { + ~provider_fail_post_initialize() override { + (*provider_destroy_count_ptr)++; + } + + umf_result_t ext_ctl(umf_ctl_query_source_t, const char *name, void *, + size_t, umf_ctl_query_type_t, va_list) noexcept { + if (name && std::string(name) == "post_initialize") { + return UMF_RESULT_ERROR_UNKNOWN; + } + + return UMF_RESULT_ERROR_INVALID_CTL_PATH; + } + }; + + provider_destroy_count_ptr = &provider_destroy_count; + + umf_memory_provider_ops_t provider_ops = + umf_test::providerMakeCOps(); + + umf_memory_provider_handle_t hProvider = nullptr; + auto ret = umfMemoryProviderCreate(&provider_ops, nullptr, &hProvider); + + ASSERT_EQ(ret, UMF_RESULT_ERROR_UNKNOWN); + ASSERT_EQ(hProvider, nullptr); + ASSERT_EQ(provider_destroy_count, 1); + provider_destroy_count_ptr = nullptr; +} + // This fixture can be instantiated with any function that accepts void // and returns any of the results listed inside the variant type. struct providerHandleCheck