diff --git a/sdk/core/azure-core/CHANGELOG.md b/sdk/core/azure-core/CHANGELOG.md index b5e36ae25..a1091caf0 100644 --- a/sdk/core/azure-core/CHANGELOG.md +++ b/sdk/core/azure-core/CHANGELOG.md @@ -5,6 +5,7 @@ ### Features Added - Add the static libcurl transport adapter. +- Add `NoSignal` option to the `curlTransportAdapter`. ### Breaking Changes diff --git a/sdk/core/azure-core/inc/azure/core/http/curl_transport.hpp b/sdk/core/azure-core/inc/azure/core/http/curl_transport.hpp index 6713e43b1..ff8db0aa4 100644 --- a/sdk/core/azure-core/inc/azure/core/http/curl_transport.hpp +++ b/sdk/core/azure-core/inc/azure/core/http/curl_transport.hpp @@ -88,6 +88,16 @@ namespace Azure { namespace Core { namespace Http { * */ CurlTransportSslOptions SslOptions; + + /** + * @brief When true, libcurl will not use any functions that install signal handlers or any + * functions that cause signals to be sent to the process. + * + * @details This option is here to allow multi-threaded unix applications to still set/use all + * timeout options etc, without risking getting signals. + * + */ + bool NoSignal = false; }; /** diff --git a/sdk/core/azure-core/inc/azure/core/http/static_curl_transport.hpp b/sdk/core/azure-core/inc/azure/core/http/static_curl_transport.hpp index 0adafe35a..9f7f89436 100644 --- a/sdk/core/azure-core/inc/azure/core/http/static_curl_transport.hpp +++ b/sdk/core/azure-core/inc/azure/core/http/static_curl_transport.hpp @@ -93,6 +93,16 @@ namespace Azure { namespace Core { namespace Http { * */ StaticCurlTransportSslOptions SslOptions; + + /** + * @brief When true, libcurl will not use any functions that install signal handlers or any + * functions that cause signals to be sent to the process. + * + * @details This option is here to allow multi-threaded unix applications to still set/use all + * timeout options etc, without risking getting signals. + * + */ + bool NoSignal = false; }; /** diff --git a/sdk/core/azure-core/src/http/curl/curl.cpp b/sdk/core/azure-core/src/http/curl/curl.cpp index 4c957995c..4397e3742 100644 --- a/sdk/core/azure-core/src/http/curl/curl.cpp +++ b/sdk/core/azure-core/src/http/curl/curl.cpp @@ -1226,38 +1226,12 @@ namespace { inline std::string GetConnectionKey(std::string const& host, CurlTransportOptions const& options) { std::string key(host); - if (!options.CAInfo.empty()) - { - key.append(options.CAInfo); - } - else - { - key.append("0"); - } - if (!options.Proxy.empty()) - { - key.append(options.Proxy); - } - else - { - key.append("0"); - } - if (!options.SslOptions.EnableCertificateRevocationListCheck) - { - key.append("1"); - } - else - { - key.append("0"); - } - if (options.SslVerifyPeer) - { - key.append("1"); - } - else - { - key.append("0"); - } + key.append(!options.CAInfo.empty() ? options.CAInfo : "0"); + key.append(!options.Proxy.empty() ? options.Proxy : "0"); + key.append(!options.SslOptions.EnableCertificateRevocationListCheck ? "1" : "0"); + key.append(options.SslVerifyPeer ? "1" : "0"); + key.append(options.NoSignal ? "1" : "0"); + return key; } } // namespace @@ -1402,7 +1376,17 @@ std::unique_ptr CurlConnectionPool::ExtractOrCreateCurlCo { throw Azure::Core::Http::TransportException( _detail::DefaultFailedToGetNewConnectionTemplate + host - + ". Failed to disable ssl verify peer." + ". " + + ". Failed to disable ssl verify peer. " + std::string(curl_easy_strerror(result))); + } + } + + if (options.NoSignal) + { + if (!SetLibcurlOption(newHandle, CURLOPT_NOSIGNAL, 1L, &result)) + { + throw Azure::Core::Http::TransportException( + _detail::DefaultFailedToGetNewConnectionTemplate + host + + ". Failed to set NOSIGNAL option for libcurl. " + std::string(curl_easy_strerror(result))); } } diff --git a/sdk/core/azure-core/src/http/curl/static_curl.cpp b/sdk/core/azure-core/src/http/curl/static_curl.cpp index dd7ac279c..37d8c2a04 100644 --- a/sdk/core/azure-core/src/http/curl/static_curl.cpp +++ b/sdk/core/azure-core/src/http/curl/static_curl.cpp @@ -289,6 +289,17 @@ public: } } + if (m_options.NoSignal) + { + if (!SetStaticLibcurlOption(m_libcurlHandle, CURLOPT_NOSIGNAL, 1L, &result)) + { + throw Azure::Core::Http::TransportException( + FailedToGetNewConnectionTemplate + host + + ". Failed to set NOSIGNAL option for libcurl. " + + std::string(curl_easy_strerror(result))); + } + } + // headers sep-up auto const& headers = request.GetHeaders(); if (headers.size() > 0) diff --git a/sdk/core/azure-core/test/ut/curl_connection_pool_test.cpp b/sdk/core/azure-core/test/ut/curl_connection_pool_test.cpp index 15eb6c3ad..e04f35cdf 100644 --- a/sdk/core/azure-core/test/ut/curl_connection_pool_test.cpp +++ b/sdk/core/azure-core/test/ut/curl_connection_pool_test.cpp @@ -45,7 +45,7 @@ namespace Azure { namespace Core { namespace Test { Azure::Core::Http::Request req( Azure::Core::Http::HttpMethod::Get, Azure::Core::Url(AzureSdkHttpbinServer::Get())); std::string const expectedConnectionKey - = AzureSdkHttpbinServer::Schema() + AzureSdkHttpbinServer::Host() + "0011"; + = AzureSdkHttpbinServer::Schema() + AzureSdkHttpbinServer::Host() + "00110"; { // Creating a new connection with default options @@ -114,7 +114,7 @@ namespace Azure { namespace Core { namespace Test { // Now test that using a different connection config won't re-use the same connection std::string const secondExpectedKey - = AzureSdkHttpbinServer::Schema() + AzureSdkHttpbinServer::Host() + "0010"; + = AzureSdkHttpbinServer::Schema() + AzureSdkHttpbinServer::Host() + "00100"; { // Creating a new connection with options Azure::Core::Http::CurlTransportOptions options; @@ -394,7 +394,7 @@ namespace Azure { namespace Core { namespace Test { Azure::Core::Http::Request req( Azure::Core::Http::HttpMethod::Get, Azure::Core::Url(authority)); std::string const expectedConnectionKey - = AzureSdkHttpbinServer::Schema() + AzureSdkHttpbinServer::Host() + "0011"; + = AzureSdkHttpbinServer::Schema() + AzureSdkHttpbinServer::Host() + "00110"; // Creating a new connection with default options auto connection = Azure::Core::Http::_detail::CurlConnectionPool::g_curlConnectionPool @@ -430,7 +430,7 @@ namespace Azure { namespace Core { namespace Test { Azure::Core::Http::Request req( Azure::Core::Http::HttpMethod::Get, Azure::Core::Url(authority)); std::string const expectedConnectionKey - = AzureSdkHttpbinServer::Schema() + AzureSdkHttpbinServer::Host() + "4430011"; + = AzureSdkHttpbinServer::Schema() + AzureSdkHttpbinServer::Host() + "44300110"; // Creating a new connection with default options auto connection = Azure::Core::Http::_detail::CurlConnectionPool::g_curlConnectionPool @@ -467,7 +467,7 @@ namespace Azure { namespace Core { namespace Test { Azure::Core::Http::Request req( Azure::Core::Http::HttpMethod::Get, Azure::Core::Url(authority)); std::string const expectedConnectionKey - = AzureSdkHttpbinServer::Schema() + AzureSdkHttpbinServer::Host() + "0011"; + = AzureSdkHttpbinServer::Schema() + AzureSdkHttpbinServer::Host() + "00110"; // Creating a new connection with default options auto connection = Azure::Core::Http::_detail::CurlConnectionPool::g_curlConnectionPool @@ -502,7 +502,7 @@ namespace Azure { namespace Core { namespace Test { Azure::Core::Http::Request req( Azure::Core::Http::HttpMethod::Get, Azure::Core::Url(authority)); std::string const expectedConnectionKey - = AzureSdkHttpbinServer::Schema() + AzureSdkHttpbinServer::Host() + "4430011"; + = AzureSdkHttpbinServer::Schema() + AzureSdkHttpbinServer::Host() + "44300110"; // Creating a new connection with default options auto connection = Azure::Core::Http::_detail::CurlConnectionPool::g_curlConnectionPool