cURL / Mailing Lists / curl-library / Single Mail

curl-library

RE: correct usage of curl_multi_setopt(_multi, CURLMOPT_SOCKETFUNCTION, _sock_cb); / curl_multi_remove_handle / curl_easy_cleanup

From: Yehezkel Horowitz <horowity_at_checkpoint.com>
Date: Tue, 14 Jan 2014 07:26:16 +0000

> int http_client_async_handler::sock_cb(CURL *e, curl_socket_t s, int what, void* per_socket_user_data)
...
> curl_multi_remove_handle(_multi, e);  // IF I CALL THIS THEN WE CRASH IN LIBCURL....   (A)
....
...                                    //        curl_easy_cleanup(context->easy);                                               (B)
>_multi = curl_multi_init();
>curl_multi_setopt(_multi, CURLMOPT_SOCKETFUNCTION, _sock_cb);

>My problem seems to be that if I use A curl crashes.
>if I use B then I get a stackoverflow when curl_easy_cleanup->Curl_close->curl_multi_remove_handle> .......curl_easy_cleanup....

> When I wrote the code I did the callbacks by trial and error but I'll have an obvious memory leak if I use the only thing that is working for me ( just skipping the curl_easy_cleanup in the destructor )

> As I see it I could remove the callback mechanism first and maybe get rid of the stack overflow but it feels like I'm missing something here. How is this supposed to be working?

You are really missing the point of how to use curl_multi_ API.
When curl_multi calls your socket callback it just request you to perform the needed action on the socket (it is still in the middle of processing the event on this socket).
It will give you the relevant easy handle, but you should not clean the easy handle (this is the destructor in C) nor remove it from the multi handle.

The time for removing from the mutli-handle and afterwards clean it (if you don't want to reuse it) is from your application context (by getting the "done" easy from the multi handle with call to curl_multi_info_read).

I mean it should be something like that:
Your application will get an event on a "socket" (in multi you are the one that listen on the sockets)
        You are calling to curl_multi_socket_action on this socket (to notify multi there is a progress)
                curl_multi understand the socket should be closed
                curl_mutli call your application to remove the socket
                        your application remove the socket (from your event queue)
                curl_multi finish whatever it should do and the call to curl_multi_socket_action is finished.
        You are checking for done messages from curl_multi
                You remove the done easy from the multi handle
                You clean the easy handle (or reset it and save for another use)
        Your application return to listen on events (or exit if there are no more transfers in the middle)...

The same goes if your application get a "timeout" event.

Hope this help you to understand the process.

PS - avoiding calling curl_easy_cleanup will just result in memory leak...

Yehezkel Horowitz

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2014-01-14