Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ class HttpOperation
std::promise<CURLcode> result_promise;
std::future<CURLcode> result_future;
};
friend class HttpOperationAccessor;
std::unique_ptr<AsyncData> async_data_;
};
} // namespace curl
Expand Down
30 changes: 26 additions & 4 deletions ext/src/http/client/curl/http_operation_curl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,28 @@ namespace client
namespace curl
{

Copy link

Copilot AI Jul 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Consider placing HttpOperationAccessor in an anonymous namespace since it’s only used within this translation unit, to avoid exporting an internal utility.

Suggested change
namespace
{

Copilot uses AI. Check for mistakes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

anonymous namespace will break the friend access.

class HttpOperationAccessor
{
public:
OPENTELEMETRY_SANITIZER_NO_THREAD static std::thread::id GetThreadId(
const HttpOperation::AsyncData &async_data)
{
#if !(defined(OPENTELEMETRY_HAVE_THREAD_SANITIZER) && OPENTELEMETRY_HAVE_THREAD_SANITIZER)
std::atomic_thread_fence(std::memory_order_acquire);
#endif
return async_data.callback_thread;
}

OPENTELEMETRY_SANITIZER_NO_THREAD static void SetThreadId(HttpOperation::AsyncData &async_data,
std::thread::id thread_id)
{
async_data.callback_thread = thread_id;
#if !(defined(OPENTELEMETRY_HAVE_THREAD_SANITIZER) && OPENTELEMETRY_HAVE_THREAD_SANITIZER)
std::atomic_thread_fence(std::memory_order_release);
#endif
}
};

size_t HttpOperation::WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
HttpOperation *self = reinterpret_cast<HttpOperation *>(userp);
Expand Down Expand Up @@ -335,7 +357,7 @@ HttpOperation::~HttpOperation()
case opentelemetry::ext::http::client::SessionState::Sending: {
if (async_data_ && async_data_->result_future.valid())
{
if (async_data_->callback_thread != std::this_thread::get_id())
if (HttpOperationAccessor::GetThreadId(*async_data_) != std::this_thread::get_id())
{
async_data_->result_future.wait();
last_curl_result_ = async_data_->result_future.get();
Expand All @@ -360,7 +382,7 @@ void HttpOperation::Finish()
if (async_data_ && async_data_->result_future.valid())
{
// We should not wait in callback from Cleanup()
if (async_data_->callback_thread != std::this_thread::get_id())
if (HttpOperationAccessor::GetThreadId(*async_data_) != std::this_thread::get_id())
{
async_data_->result_future.wait();
last_curl_result_ = async_data_->result_future.get();
Expand Down Expand Up @@ -412,9 +434,9 @@ void HttpOperation::Cleanup()
callback.swap(async_data_->callback);
if (callback)
{
async_data_->callback_thread = std::this_thread::get_id();
HttpOperationAccessor::SetThreadId(*async_data_, std::this_thread::get_id());
callback(*this);
async_data_->callback_thread = std::thread::id();
HttpOperationAccessor::SetThreadId(*async_data_, std::thread::id());
}

// Set value to promise to continue Finish()
Expand Down
Loading