> ------------------------------
> 
> Message: 3
> Date: Thu, 17 Dec 2015 00:01:30 +0100
> From: Dan Fandrich <[email protected]>
> To: [email protected]
> Subject: Re: Getting Segmentation Fault from curl_multi_perform() when
>    I add data
> Message-ID: <[email protected]>
> Content-Type: text/plain; charset=iso-8859-1
> 
> On Wed, Dec 16, 2015 at 02:04:59PM -0600, [email protected] 
wrote:
> > I am getting a segmentation fault from curl_multi_perform() when Itry 
to add
> > data.
> > 
> > My do {} while loop looks like the one on 
http://curl.haxx.se/libcurl/c/
> > multi-post.html. While my program is waiting for data the 
> curl_multi_perform()
> > is running and returning normally, as far as I can tell. When data 
becomes
> > available I set it in the easy handle using curl_easy_setopt() with 
the
> > CURLOPT_POSTFIELDS and CURLOPT_POSTFIELDSIZE enumerations.  I then add 
that
> > easy handle to my multi handle with curl_multi_add_handle().
> 
> Are you changing and adding the first handle or a second handle? You 
can't
> change a handle in mid-transfer.
 
I am adding the first handle. I have a multi and 3 easy handles created. 
My plan was that I only add the easy handles to the multi handle when I 
have data available for that easy handle. Once the transmission is 
complete for that easy handle I'd remove it from the multi handle and wait 
for more data before I add it again.

> > From what I can tell with my COUTs, it called the 
> curl_multi_perform() two more
> > times and then seg faults on the third call. What could be happening?
> 
> Run it under a debugger to see the exact line number of the code that's
> segfaulting. If you still can't figure it out, please post code that
> demonstrates the problem.
>
It appears that the offending line of code is the curl_multi_perform(). I 
had a COUT in front and right after the call.
 

Here is a snippet of the code. It fails after the easy handle is added to 
the multi-handle. Before the easy handle is added the multi-handle is 
"empty". I am using libcurl.so version 5.3.0. I was using a callback 
function but I took all that out trying to figure out what's happening. I 
was using curl_easy_perform() to handle all 3 connections but I thought 
this would be a better interface but I can't get it to work! It was 
working just fine with the easy interface. I'd really like to use the 
multi interface because I'd like to add more handles.

This is a worker function in a thread. My application is multi-threaded 
but only this thread is using the libcurl library.

(Note: You can see some of the code where I only initialize 1 handle 
instead of 3. This was just a test.)

void Class1::Worker_Function()
{
        bool Curl_initialized = false;
        CURLcode result = CURLE_OK;
        char CURL_ERROR_MESSAGES[CURL_ERROR_SIZE];
        long ResponseCode;
        struct Struct_Type Struct1;
        struct Struct_Type Struct2;
        struct Struct_Type Struct3;
        CURL *handles[3];
        CURLM *multi_handle;
        int32_t still_running;
        CURLMsg *msg;
        int32_t msgs_left;
        int32_t numfds;
 
        CURLMcode tmp;

        struct curl_slist *list = NULL;
 
        // Set the headers for this message
        list = curl_slist_append(list, "Content-Type: application/json");
        list = curl_slist_append(list, "Accept: application/json");
 
        //for (CURL *CHandle : handles)
        for (int i=0; i < 1; i++)
        {
                handles[i] = curl_easy_init();
                // Set the data that we want to send
                curl_easy_setopt(handles[i], CURLOPT_INTERFACE, "eth1");
                // Do not get the header information in the response
                curl_easy_setopt(handles[i], CURLOPT_HEADER, 0L);
                // Configure an error buffer for error messages
                curl_easy_setopt(handles[i], CURLOPT_ERRORBUFFER, 
CURL_ERROR_MESSAGES);
                curl_easy_setopt(handles[i], CURLOPT_PROXY, "
http://Proxyserver";);
                curl_easy_setopt(handles[i], CURLOPT_PROXYPORT, 80);
                curl_easy_setopt(handles[i], CURLOPT_PROXYUSERPWD, 
"username:password");
 
                // Write the list of HTTP headers
                curl_easy_setopt(handles[i], CURLOPT_HTTPHEADER, list);
        }
        if (list != NULL)
        {
                // Free the list.
                curl_slist_free_all(list);
        }
 
        std::cout << "Start setting the URLs\n";
 
        // Set the URL 
        curl_easy_setopt(handles[0], CURLOPT_URL, "
http://www.example.com/v1";);

        // Set the URL 
        curl_easy_setopt(handles[1], CURLOPT_URL, "
http://www.example.com/v2";);

        // Set the URL 
        curl_easy_setopt(handles[2], CURLOPT_URL, "
http://www.example.com/v3";);

        std::cout << "Init the Multi Handle\n";
        // Initialize our multi handle
        multi_handle = curl_multi_init();
 
        curl_multi_perform(multi_handle, &still_running);

        while (1)
        {
                // Clear out the messages
                Struct1.Request.clear();
                Struct1.Response.clear();
                Struct1.JSON_Request.clear();

                Struct2.Request.clear();
                Struct2.Response.clear();
                Struct2.JSON_Request.clear();

                Struct3.Response.clear();

                // Lock access to the Queue
                std::lock_guard<std::mutex> 
lock_Queue(Class1::data_Q_Mutex);
 
                // Check to see if the queue is empty
                while (Class1::Data.empty() == false)
                {
                        // There is something in the queue so peek at the 
item
                        if (Class1::Data.front().Packet_Type == Type1)
                        {
                                // Develop a JSON packet to activate the 
node and then serialize it
 JsonSerializer::Serialize(Struct1.JSON_Request, &(Class1::Data.front()), 
Struct1.Request);
                                // Duplicate this effort to create the 
control packet and then serialize it
 JsonSerializer::Serialize(Struct3.JSON_Request, &(Class1::Data.front()), 
Struct3.Request);
                        }
                        // The Packet must be a data packet
                        else
                        {
                                // Develop a JSON packet to record the 
data and then serialize it
 JsonSerializer::Serialize(Struct2.JSON_Request, &(Class1::Data.front()), 
Struct2.Request);
                        }
                        Class1::Data.pop();
                }
                // Release access to the Cloud queue
                lock_Queue.~lock_guard();

                // Check to see if there is an Activate message ready
                if (Struct1.Request.empty() == false)
                {
                        // Set the data that we want to send
                        curl_easy_setopt(handles[0], CURLOPT_POSTFIELDS, 
Struct1.Request.c_str());
                        //curl_easy_setopt(handles[0], CURLOPT_POSTFIELDS, 
"Hello");
                        // Set the data size
                        curl_easy_setopt(handles[0], 
CURLOPT_POSTFIELDSIZE, (ulong32_t)Struct1.Request.length());
                        //curl_easy_setopt(handles[0], 
CURLOPT_POSTFIELDSIZE, 5);
                        std::cout << "Struct1\n";
                        // Add the handle in to the multihandle
                        tmp = curl_multi_add_handle(multi_handle, 
handles[0]);
                        std::cout << "Handle Added: tmp = " << tmp << 
"\n";
                }
 
                if (Struct2.Request.empty() == false)
                {
                        // Set the data that we want to send
                        curl_easy_setopt(handles[1], CURLOPT_POSTFIELDS, 
Struct2.Request.c_str());
                        // Set the data size
                        curl_easy_setopt(handles[1], 
CURLOPT_POSTFIELDSIZE, (ulong32_t)Struct2.Request.length());
                        //std::cout << "Struct2\n";
                        // Add the handle in to the multihandle
                        curl_multi_add_handle(multi_handle, handles[1]);
                }
 
                if (Struct3.Request.empty() == false)
                {
                        // Set the data that we want to send
                        curl_easy_setopt(handles[2], CURLOPT_POSTFIELDS, 
Struct3.Request.c_str());
                        // Set the data size
                        curl_easy_setopt(handles[2], 
CURLOPT_POSTFIELDSIZE, (ulong32_t)Struct3.Request.length());
                        //std::cout << "Struct3\n";
                        // Add the handle in to the multihandle
                        curl_multi_add_handle(multi_handle, handles[2]);
                } 

                numfds = 0;
                do 
                {
                        struct timeval timeout;
                        int rc;
                        CURLMcode mc;

                        fd_set fdread;
                        fd_set fdwrite;
                        fd_set fdexcep;
                        int maxfd = -1;
                        long curl_timeo = -1;

                        FD_ZERO(&fdread);
                        FD_ZERO(&fdwrite);
                        FD_ZERO(&fdexcep);

                        timeout.tv_sec = 1;
                        timeout.tv_usec = 0;

                        curl_multi_timeout(multi_handle, &curl_timeo);
                        if (curl_timeo >= 0)
                        {
                                timeout.tv_sec = curl_timeo/1000;
                                if (timeout.tv_sec > 1)
                                {
                                        timeout.tv_sec = 1;
                                }
                                else
                                {
                                        timeout.tv_usec = (curl_timeo % 
1000) * 1000;
                                }
                        }

                        mc = curl_multi_fdset(multi_handle, &fdread, 
&fdwrite, &fdexcep, &maxfd);

                        if (maxfd == -1)
                        {
                                struct timeval wait = {0, 100 * 1000 };
                                rc = select(0, NULL, NULL, NULL, &wait);
                        }
                        else
                        {
                                rc = select(maxfd+1, &fdread, &fdwrite, 
&fdexcep, &timeout);
                        }

                        switch (rc)
                        {
                        case -1:
                                break;
                        case 0:
                        default:
                                curl_multi_perform(multi_handle, 
&still_running);
                                std::cout << "after send. still_running=" 
<< still_running << "\n";
                                break;
                        }

                        //std::cout << "Before Wait: numfds= " << numfds 
<< "\n";
                        //tmp = curl_multi_wait(multi_handle, NULL, 0, 
10000, &numfds);
                        //std::cout << "After Wait tmp=" << tmp << "\n 
Before send. still running: " << still_running << "\n";
                        // Attempt to perform some action
                        //tmp = curl_multi_perform(multi_handle, 
&still_running);

                } while (still_running);
 
                // Check to see how the transfers went
                while ((msg = curl_multi_info_read(multi_handle, 
&msgs_left)))
                {
                        if (msg->msg == CURLMSG_DONE)
                        {
                                std::cout << "Remove a handle since we're 
done\n";
                                // Remove the handle
                                curl_multi_remove_handle(multi_handle, 
msg->easy_handle);
                        }
                }
                // Sleep for an amount of time.
                nanosleep(&req, NULL);
        }
}



> >>> Dan
> 
> 
> ------------------------------




/**************************************************
Heath Schaefer
Product Engineer
Sporlan Division, Parker Hannifin Corporation
636.392.3243
**************************************************/




-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html

Reply via email to