@@ -43,49 +43,49 @@ CurlMultiManager::~CurlMultiManager() {
4343 curl_slist_free_all (header_it->second );
4444 }
4545
46- curl_easy_cleanup (easy);
46+ // curl_easy_cleanup(easy);
4747 }
4848 }
4949}
5050
51- void CurlMultiManager::add_handle (CURL * easy,
51+ void CurlMultiManager::add_handle (std::shared_ptr< CURL > easy,
5252 curl_slist* headers,
5353 CompletionCallback callback) {
54- {
55- std::lock_guard lock (mutex_);
56- callbacks_[easy] = std::move (callback);
57- headers_[easy] = headers;
58- }
59-
60- if (const CURLMcode rc = curl_multi_add_handle (multi_handle_.get (), easy);
54+ if (const CURLMcode rc = curl_multi_add_handle (
55+ multi_handle_.get (), easy.get ());
6156 rc != CURLM_OK ) {
62- std::lock_guard lock (mutex_);
63- callbacks_.erase (easy);
64-
6557 // Free headers on error
66- if (const auto header_it = headers_.find (easy);
67- header_it != headers_.end () && header_it->second ) {
68- curl_slist_free_all (header_it->second );
58+ if (headers) {
59+ curl_slist_free_all (headers);
6960 }
70- headers_.erase (easy);
7161
7262 std::cerr << " Failed to add handle to multi: "
7363 << curl_multi_strerror (rc) << std::endl;
64+ return ;
65+ }
66+
67+ {
68+ std::lock_guard lock (mutex_);
69+ callbacks_[easy.get ()] = std::move (callback);
70+ headers_[easy.get ()] = headers;
71+ handles_[easy.get ()] = easy;
7472 }
7573}
7674
7775void CurlMultiManager::remove_handle (CURL * easy) {
7876 curl_multi_remove_handle (multi_handle_.get (), easy);
7977
8078 std::lock_guard lock (mutex_);
81- callbacks_.erase (easy);
8279
8380 // Free headers if they exist
8481 if (const auto header_it = headers_.find (easy);
8582 header_it != headers_.end () && header_it->second ) {
8683 curl_slist_free_all (header_it->second );
8784 }
85+
86+ callbacks_.erase (easy);
8887 headers_.erase (easy);
88+ handles_.erase (easy);
8989}
9090
9191int CurlMultiManager::socket_callback (CURL * easy,
@@ -182,17 +182,21 @@ void CurlMultiManager::check_multi_info() {
182182 curl_slist* headers = nullptr ;
183183 {
184184 std::lock_guard lock (mutex_);
185+
185186 if (auto it = callbacks_.find (easy); it != callbacks_.end ()) {
186187 callback = std::move (it->second );
187188 callbacks_.erase (it);
188189 }
190+ callbacks_.erase (easy);
189191
190192 // Get and remove headers
191193 if (auto header_it = headers_.find (easy);
192194 header_it != headers_.end ()) {
193195 headers = header_it->second ;
194196 headers_.erase (header_it);
195197 }
198+
199+ handles_.erase (easy);
196200 }
197201
198202 // Remove from multi handle
@@ -224,10 +228,12 @@ void CurlMultiManager::start_socket_monitor(SocketInfo* socket_info,
224228 // Assign the CURL socket to the ASIO socket
225229 // tcp::socket::assign works with native socket handles on both platforms
226230 boost::system::error_code ec;
227- socket_info->handle ->assign (boost::asio::ip::tcp::v4 (), socket_info->sockfd , ec);
231+ socket_info->handle ->assign (boost::asio::ip::tcp::v4 (),
232+ socket_info->sockfd , ec);
228233
229234 if (ec) {
230- std::cerr << " Failed to assign socket: " << ec.message () << std::endl;
235+ std::cerr << " Failed to assign socket: " << ec.message () <<
236+ std::endl;
231237 socket_info->handle .reset ();
232238 return ;
233239 }
@@ -249,36 +255,41 @@ void CurlMultiManager::start_socket_monitor(SocketInfo* socket_info,
249255
250256 // Create and store handler in SocketInfo to keep it alive
251257 // Use weak_ptr in capture to avoid circular reference
252- socket_info->read_handler = std::make_shared<std::function<void ()>>();
253- std::weak_ptr<std::function<void ()>> weak_read_handler = socket_info->read_handler ;
254- *socket_info->read_handler = [weak_self, sockfd, weak_handle, weak_read_handler]() {
255- // Check if manager and handle are still valid
256- const auto self = weak_self.lock ();
257- const auto handle = weak_handle.lock ();
258- if (!self || !handle) {
259- return ;
260- }
258+ socket_info->read_handler = std::make_shared<std::function<void
259+ ()>>();
260+ std::weak_ptr<std::function<void ()>> weak_read_handler = socket_info
261+ ->read_handler ;
262+ *socket_info->read_handler = [weak_self, sockfd, weak_handle,
263+ weak_read_handler]() {
264+ // Check if manager and handle are still valid
265+ const auto self = weak_self.lock ();
266+ const auto handle = weak_handle.lock ();
267+ if (!self || !handle) {
268+ return ;
269+ }
261270
262- handle->async_wait (
263- boost::asio::ip::tcp::socket::wait_read,
264- [weak_self, sockfd, weak_handle, weak_read_handler](
271+ handle->async_wait (
272+ boost::asio::ip::tcp::socket::wait_read,
273+ [weak_self, sockfd, weak_handle, weak_read_handler](
265274 const boost::system::error_code& ec) {
266- // If operation was canceled or had an error, don't re-register
267- if (ec) {
268- return ;
269- }
270-
271- if (const auto self = weak_self.lock ()) {
272- self->handle_socket_action (sockfd, CURL_CSELECT_IN );
273-
274- // Always try to re-register for continuous monitoring
275- // The validity check at the top of read_handler will stop it if needed
276- if (const auto handler = weak_read_handler.lock ()) {
277- (*handler)(); // Recursive call
275+ // If operation was canceled or had an error, don't re-register
276+ if (ec) {
277+ return ;
278+ }
279+
280+ if (const auto self = weak_self.lock ()) {
281+ self->handle_socket_action (
282+ sockfd, CURL_CSELECT_IN );
283+
284+ // Always try to re-register for continuous monitoring
285+ // The validity check at the top of read_handler will stop it if needed
286+ if (const auto handler = weak_read_handler.
287+ lock ()) {
288+ (*handler)(); // Recursive call
289+ }
278290 }
279- }
280- });
281- };
291+ });
292+ };
282293 (*socket_info->read_handler )(); // Initial call
283294 }
284295 }
@@ -292,36 +303,41 @@ void CurlMultiManager::start_socket_monitor(SocketInfo* socket_info,
292303
293304 // Create and store handler in SocketInfo to keep it alive
294305 // Use weak_ptr in capture to avoid circular reference
295- socket_info->write_handler = std::make_shared<std::function<void ()>>();
296- std::weak_ptr<std::function<void ()>> weak_write_handler = socket_info->write_handler ;
297- *socket_info->write_handler = [weak_self, sockfd, weak_handle, weak_write_handler]() {
298- // Check if manager and handle are still valid
299- const auto self = weak_self.lock ();
300- const auto handle = weak_handle.lock ();
301- if (!self || !handle) {
302- return ;
303- }
306+ socket_info->write_handler = std::make_shared<std::function<void
307+ ()>>();
308+ std::weak_ptr<std::function<void ()>> weak_write_handler =
309+ socket_info->write_handler ;
310+ *socket_info->write_handler = [weak_self, sockfd, weak_handle,
311+ weak_write_handler]() {
312+ // Check if manager and handle are still valid
313+ const auto self = weak_self.lock ();
314+ const auto handle = weak_handle.lock ();
315+ if (!self || !handle) {
316+ return ;
317+ }
304318
305- handle->async_wait (
306- boost::asio::ip::tcp::socket::wait_write,
307- [weak_self, sockfd, weak_handle, weak_write_handler](
319+ handle->async_wait (
320+ boost::asio::ip::tcp::socket::wait_write,
321+ [weak_self, sockfd, weak_handle, weak_write_handler](
308322 const boost::system::error_code& ec) {
309- // If operation was canceled or had an error, don't re-register
310- if (ec) {
311- return ;
312- }
313-
314- if (const auto self = weak_self.lock ()) {
315- self->handle_socket_action (sockfd, CURL_CSELECT_OUT );
316-
317- // Always try to re-register for continuous monitoring
318- // The validity check at the top of write_handler will stop it if needed
319- if (const auto handler = weak_write_handler.lock ()) {
320- (*handler)(); // Recursive call
323+ // If operation was canceled or had an error, don't re-register
324+ if (ec) {
325+ return ;
326+ }
327+
328+ if (const auto self = weak_self.lock ()) {
329+ self->handle_socket_action (
330+ sockfd, CURL_CSELECT_OUT );
331+
332+ // Always try to re-register for continuous monitoring
333+ // The validity check at the top of write_handler will stop it if needed
334+ if (const auto handler = weak_write_handler.
335+ lock ()) {
336+ (*handler)(); // Recursive call
337+ }
321338 }
322- }
323- });
324- };
339+ });
340+ };
325341 (*socket_info->write_handler )(); // Initial call
326342 }
327343 }
0 commit comments