diff --git a/docs/Memory_Management.md b/docs/Memory_Management.md index 109b1a1b4fb..007b2a079ef 100644 --- a/docs/Memory_Management.md +++ b/docs/Memory_Management.md @@ -1,7 +1,7 @@ # Memory Management The AWS SDK for C++ provides a way to control memory allocation and deallocation in a library. -Custom memory management is available only if you use a version of the library built using the compile-time constant AWS_CUSTOM_MEMORY_MANAGEMENT defined. +Custom memory management is available only if you use a version of the library built using the compile-time constant USE_AWS_MEMORY_MANAGEMENT defined. If you use a version of the library built without the compile-time constant, the global memory system functions such as InitializeAWSMemorySystem will not work and the global new and delete functions will be used instead. @@ -48,7 +48,7 @@ When initialized with a memory manager, the AWS SDK for C++ defers all allocatio If you use custom STL allocators, you must alter the type signatures for all STL objects to match the allocation policy. Because STL is used prominently in the SDK implementation and interface, a single approach in the SDK would inhibit direct passing of default STL objects into the SDK or control of STL allocation. Alternately, a hybrid approach – using custom allocators internally and allowing standard and custom STL objects on the interface – could potentially cause more difficulty when investigating memory issues. -The solution is to use the memory system’s compile-time constant AWS_CUSTOM_MEMORY_MANAGEMENT to control which STL types the SDK will use. +The solution is to use the memory system’s compile-time constant USE_AWS_MEMORY_MANAGEMENT to control which STL types the SDK will use. If the compile-time constant is enabled (on), the types resolve to STL types with a custom allocator connected to the AWS memory system. @@ -57,7 +57,7 @@ If the compile-time constant is disabled (off), all Aws::* types resolve to the Example code from the AWSAllocator.h file in the SDK: ```cpp -#ifdef AWS_CUSTOM_MEMORY_MANAGEMENT +#ifdef USE_AWS_MEMORY_MANAGEMENT template< typename T > class AwsAllocator : public std::allocator< T > diff --git a/docs/SDK_usage_guide.md b/docs/SDK_usage_guide.md index b34706aeb7f..287aca1f126 100644 --- a/docs/SDK_usage_guide.md +++ b/docs/SDK_usage_guide.md @@ -8,7 +8,7 @@ Several directories are appended with \*integration-tests. After building your p ## Build Defines If you dynamically link to the SDK you will need to define the USE_IMPORT_EXPORT symbol for all build targets using the SDK. -If you wish to install your own memory manager to handle allocations made by the SDK, you will need to pass the CUSTOM_MEMORY_MANAGEMENT cmake parameter (-DCUSTOM_MEMORY_MANAGEMENT) as well as define AWS_CUSTOM_MEMORY_MANAGEMENT in all build targets dependent on the SDK. +If you wish to install your own memory manager to handle allocations made by the SDK, you will need to pass the CUSTOM_MEMORY_MANAGEMENT cmake parameter (-DCUSTOM_MEMORY_MANAGEMENT) as well as define USE_AWS_MEMORY_MANAGEMENT in all build targets dependent on the SDK. Note, if you use our export file, this will be handled automatically for you. We recommend you use our export file to handle this for you: https://aws.amazon.com/blogs/developer/using-cmake-exports-with-the-aws-sdk-for-c/ diff --git a/src/aws-cpp-sdk-core/source/client/RequestCompression.cpp b/src/aws-cpp-sdk-core/source/client/RequestCompression.cpp index 2a93bc15428..8b1524b337d 100644 --- a/src/aws-cpp-sdk-core/source/client/RequestCompression.cpp +++ b/src/aws-cpp-sdk-core/source/client/RequestCompression.cpp @@ -74,7 +74,7 @@ void aws_zfree(void * /* opaque */, void * ptr) } } -#endif // AWS_CUSTOM_MEMORY_MANAGEMENT +#endif // USE_AWS_MEMORY_MANAGEMENT #endif // ENABLED_ZLIB_REQUEST_COMPRESSION diff --git a/src/aws-cpp-sdk-core/source/http/HttpClientFactory.cpp b/src/aws-cpp-sdk-core/source/http/HttpClientFactory.cpp index 51453adf103..0ea1fef1e31 100644 --- a/src/aws-cpp-sdk-core/source/http/HttpClientFactory.cpp +++ b/src/aws-cpp-sdk-core/source/http/HttpClientFactory.cpp @@ -4,6 +4,7 @@ */ #include +#include #if AWS_SDK_USE_CRT_HTTP #include @@ -181,6 +182,9 @@ namespace Aws { if(GetHttpClientFactory()) { + // EC2 metadata client uses http client from a factory, it will be invalidated + Aws::Internal::CleanupEC2MetadataClient(); + GetHttpClientFactory()->CleanupStaticState(); GetHttpClientFactory() = nullptr; } @@ -188,8 +192,14 @@ namespace Aws void SetHttpClientFactory(const std::shared_ptr& factory) { + bool recreateEC2Client = Aws::Internal::GetEC2MetadataClient() ? true : false; CleanupHttp(); GetHttpClientFactory() = factory; + + if (recreateEC2Client) + { + Aws::Internal::InitEC2MetadataClient(); + } } std::shared_ptr CreateHttpClient(const Aws::Client::ClientConfiguration& clientConfiguration) diff --git a/src/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp b/src/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp index 742cde7b75b..b721d5e78da 100644 --- a/src/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp +++ b/src/aws-cpp-sdk-core/source/http/curl/CurlHttpClient.cpp @@ -25,7 +25,7 @@ using namespace Aws::Utils; using namespace Aws::Utils::Logging; using namespace Aws::Monitoring; -#ifdef AWS_CUSTOM_MEMORY_MANAGEMENT +#ifdef USE_AWS_MEMORY_MANAGEMENT static const char* MemTag = "libcurl"; static size_t offset = sizeof(size_t); @@ -505,11 +505,16 @@ void CurlHttpClient::InitGlobalState() AWS_LOGSTREAM_INFO(CURL_HTTP_CLIENT_TAG, "Initializing Curl library with version: " << curlVersionData->version << ", ssl version: " << curlVersionData->ssl_version); isInit = true; -#ifdef AWS_CUSTOM_MEMORY_MANAGEMENT - curl_global_init_mem(CURL_GLOBAL_ALL, &malloc_callback, &free_callback, &realloc_callback, &strdup_callback, &calloc_callback); +#ifdef USE_AWS_MEMORY_MANAGEMENT + CURLcode curlResponseCode = curl_global_init_mem(CURL_GLOBAL_ALL, &malloc_callback, &free_callback, &realloc_callback, &strdup_callback, &calloc_callback); #else - curl_global_init(CURL_GLOBAL_ALL); + CURLcode curlResponseCode = curl_global_init(CURL_GLOBAL_ALL); #endif + if (curlResponseCode != CURLE_OK) + { + AWS_LOGSTREAM_FATAL(CURL_HTTP_CLIENT_TAG, "Failed to init curl, return code " << curlResponseCode); + isInit = false; + } } } @@ -517,6 +522,7 @@ void CurlHttpClient::InitGlobalState() void CurlHttpClient::CleanupGlobalState() { curl_global_cleanup(); + isInit = false; } Aws::String CurlInfoTypeToString(curl_infotype type) diff --git a/src/aws-cpp-sdk-core/source/internal/AWSHttpResourceClient.cpp b/src/aws-cpp-sdk-core/source/internal/AWSHttpResourceClient.cpp index 2af39e6098f..a559090e7a3 100644 --- a/src/aws-cpp-sdk-core/source/internal/AWSHttpResourceClient.cpp +++ b/src/aws-cpp-sdk-core/source/internal/AWSHttpResourceClient.cpp @@ -131,10 +131,20 @@ namespace Aws AmazonWebServiceResult AWSHttpResourceClient::GetResourceWithAWSWebServiceResult(const std::shared_ptr &httpRequest) const { AWS_LOGSTREAM_TRACE(m_logtag.c_str(), "Retrieving credentials from " << httpRequest->GetURIString()); + if (!m_httpClient) + { + AWS_LOGSTREAM_FATAL(m_logtag.c_str(), "Unable to get a response: missing http client!"); + return {{}, {}, HttpResponseCode::REQUEST_NOT_MADE}; + } for (long retries = 0;; retries++) { std::shared_ptr response(m_httpClient->MakeRequest(httpRequest)); + if (!response) + { + AWS_LOGSTREAM_FATAL(m_logtag.c_str(), "Unable to get a response: http client returned a nullptr!"); + return {{}, {}, HttpResponseCode::NO_RESPONSE}; + } if (response->GetResponseCode() == HttpResponseCode::OK) { diff --git a/tests/aws-cpp-sdk-ec2-integration-tests/EC2TestsDualStack.cpp b/tests/aws-cpp-sdk-ec2-integration-tests/EC2TestsDualStack.cpp index 56fb040ab8c..9c8d94e9282 100644 --- a/tests/aws-cpp-sdk-ec2-integration-tests/EC2TestsDualStack.cpp +++ b/tests/aws-cpp-sdk-ec2-integration-tests/EC2TestsDualStack.cpp @@ -43,7 +43,7 @@ TEST_F(EC2DualStackTests, TestDualStackMocked) goodResponse->GetResponseBody() << goodReply; mockHttpClient->AddResponseToReturn(goodResponse); - Aws::Client::ClientConfiguration clientConfig; + Aws::Client::ClientConfiguration clientConfig("default", true); clientConfig.region = "us-east-1"; clientConfig.useDualStack = true; @@ -69,7 +69,7 @@ TEST_F(EC2DualStackTests, TestDualStackMocked) TEST_F(EC2DualStackTests, TestDualStackEndpoint) { - Aws::Client::ClientConfiguration clientConfig; + Aws::Client::ClientConfiguration clientConfig("default", true); clientConfig.region = "us-east-1"; clientConfig.useDualStack = true; diff --git a/tests/aws-cpp-sdk-eventbridge-tests/EventBridgeTests.cpp b/tests/aws-cpp-sdk-eventbridge-tests/EventBridgeTests.cpp index 3aee4e542ae..cd0892f4143 100644 --- a/tests/aws-cpp-sdk-eventbridge-tests/EventBridgeTests.cpp +++ b/tests/aws-cpp-sdk-eventbridge-tests/EventBridgeTests.cpp @@ -74,7 +74,7 @@ static std::shared_ptr buildEventBrid TEST_F(EventBridgeTests, TestPutEventsBasic) { - Aws::Client::ClientConfiguration clientConfig; + Aws::Client::ClientConfiguration clientConfig("default", true); clientConfig.region = "us-east-1"; Aws::Auth::AWSCredentials mockCreds("accessKey", "secretKey", "sessionToken"); @@ -100,7 +100,7 @@ TEST_F(EventBridgeTests, TestPutEventsBasic) TEST_F(EventBridgeTests, TestPutEventsMultiRegional) { - Aws::Client::ClientConfiguration clientConfig; + Aws::Client::ClientConfiguration clientConfig("default", true); clientConfig.region = "us-east-1"; Aws::Auth::AWSCredentials mockCreds("accessKey", "secretKey", "sessionToken"); @@ -168,7 +168,7 @@ TEST_F(EventBridgeTests, TestPutEventsEndpointTests) for(size_t tcIdx = 0; tcIdx < TEST_CASES.size(); ++tcIdx) { const EventBridgeEndpointTestCase& testCase = TEST_CASES[tcIdx]; - Aws::Client::ClientConfiguration clientConfig; + Aws::Client::ClientConfiguration clientConfig("default", true); clientConfig.region = testCase.clientRegion; clientConfig.useDualStack = testCase.useDualStackEndpoint; clientConfig.useFIPS = testCase.useFipsEndpoint;