Skip to content

Commit 2e8d74e

Browse files
committed
Keep active curl handles out of in-transfer state callbacks
Copilot comment 4114543078: sample listeners in examples/cpp/SampleCpp/DebugCallback.cpp:79-86 and examples/cpp/MacProxy/HttpEventListener.cpp:38-45 set options on non-null handles. OnSending on curl 7.80+ now passes null while OnConnecting retains its pre-transfer handle; legacy timing and handle access stay unchanged. Files changed: lib/http/HttpClient_Curl.hpp, lib/include/public/IHttpClient.hpp, tests/unittests/HttpClientCurlTests.cpp. Document callback handle availability and assert both runtime paths in loopback tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5fa346e8-a5c8-4324-8144-a4a867cb146e
1 parent c0baa83 commit 2e8d74e

3 files changed

Lines changed: 13 additions & 3 deletions

File tree

‎lib/http/HttpClient_Curl.hpp‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,10 @@ class CurlHttpOperation {
170170
if (m_callback != nullptr)
171171
{
172172
HookScope callbackScope(m_callbackHooks);
173-
m_callback->OnHttpStateEvent(type, static_cast<void*>(curl), 0);
173+
// OnSending runs inside curl_easy_perform with the prereq callback.
174+
// Do not expose a handle observers could mutate during that transfer.
175+
void* handle = (m_usePrereqCallback && type == OnSending) ? nullptr : static_cast<void*>(curl);
176+
m_callback->OnHttpStateEvent(type, handle, 0);
174177
}
175178
}
176179

‎lib/include/public/IHttpClient.hpp‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,9 @@ namespace MAT_NS_BEGIN
500500
///
501501
/// </summary>
502502
/// <param name="state">HttpStateEvent - see diagram</param>
503-
/// <param name="data">HTTP client implementation-specific data structure (optional)</param>
503+
/// <param name="data">HTTP client implementation-specific data structure (optional).
504+
/// On curl 7.80+ the OnSending event runs within a libcurl transfer and does not
505+
/// expose its active handle; configure curl options from OnConnecting instead.</param>
504506
/// <param name="size">HTTP client implementation-specific data structure size (optional)</param>
505507
virtual void OnHttpStateEvent(HttpStateEvent state, void* data = nullptr, size_t size = 0)
506508
{

‎tests/unittests/HttpClientCurlTests.cpp‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,11 +188,13 @@ TEST_F(HttpClientCurlHeaderTests, CapturesResponseHeadersAndBody)
188188
struct StateCallback : public IHttpResponseCallback
189189
{
190190
std::vector<HttpStateEvent> states;
191+
std::vector<void*> handles;
191192

192193
void OnHttpResponse(IHttpResponse* response) override { delete response; }
193-
void OnHttpStateEvent(HttpStateEvent state, void*, size_t) override
194+
void OnHttpStateEvent(HttpStateEvent state, void* handle, size_t) override
194195
{
195196
states.push_back(state);
197+
handles.push_back(handle);
196198
}
197199
} callback;
198200

@@ -212,6 +214,9 @@ TEST_F(HttpClientCurlHeaderTests, CapturesResponseHeadersAndBody)
212214
EXPECT_EQ(responseHeaders.at("X-MAT-Test"), "header-value");
213215
EXPECT_EQ(std::string(responseBody.begin(), responseBody.end()), "body-value");
214216
EXPECT_EQ(callback.states, (std::vector<HttpStateEvent>{OnCreated, OnConnecting, OnSending, OnResponse}));
217+
ASSERT_EQ(callback.handles.size(), 4u);
218+
EXPECT_EQ(callback.handles[1], operation.GetHandle());
219+
EXPECT_EQ(callback.handles[2], UsesPrereqCallback() ? nullptr : operation.GetHandle());
215220
EXPECT_EQ(m_server.acceptedConnections(), UsesPrereqCallback() ? 1u : 2u);
216221
}
217222

0 commit comments

Comments
 (0)