curl-library
Re: Getting Segmentation Fault from curl_multi_perform() whenI add data
Date: Thu, 17 Dec 2015 08:44:46 -0600
> ------------------------------
>
> Message: 3
> Date: Thu, 17 Dec 2015 00:01:30 +0100
> From: Dan Fandrich <dan_at_coneharvesters.com>
> To: curl-library_at_cool.haxx.se
> Subject: Re: Getting Segmentation Fault from curl_multi_perform() when
> I add data
> Message-ID: <20151216230130.GC2770_at_coneharvesters.com>
> Content-Type: text/plain; charset=iso-8859-1
>
> On Wed, Dec 16, 2015 at 02:04:59PM -0600, heath.schaefer_at_parker.com
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
Received on 2015-12-17