Bugs item #1833734, was opened at 2007-11-17 18:31
Message generated for change (Comment added) made by gdding
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=100976&aid=1833734&group_id=976
Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: libcurl
Group: crash
Status: Open
Resolution: None
Priority: 7
Private: No
Submitted By: Guodong Ding (gdding)
Assigned to: Daniel Stenberg (bagder)
Summary: Curl_llist_insert_next crashes occasionally
Initial Comment:
libcurl version: 7.17.1
Platform: winxp 32-bit + VS.NET2003
Sometimes the function Curl_llist_insert_next() crashes, for the value of parameter 'e' is zero when list->size > 0. See the following code line:
ne->next = e->next;
----------------------------------------------------------------------
>Comment By: Guodong Ding (gdding)
Date: 2007-11-18 15:31
Message:
Logged In: YES
user_id=1939640
Originator: YES
I used the multi interface. The following is the focus part of my source
code. The multi interfaces are called and used mainly in the GatherCore()
function.
/*************************************************/
unsigned int CPageGather::m_nGlobalInitCount = 0;
#ifdef WIN32
void CPageGather::GatherCoreThread(void *p)
{
CPageGather *pGather = (CPageGather*)p;
if (pGather != NULL)
{
pGather->GatherCore();
}
}
#else
void* CPageGather::GatherCoreThread(void *p)
{
CPageGather *pGather = (CPageGather*)p;
if (pGather != NULL)
{
pGather->GatherCore();
}
return NULL;
}
#endif
size_t CPageGather::WriteDataCallback(void *ptr, size_t size, size_t
nmemb, void *data)
{
TEasyCURLInfo* pEasyCURLInfo = (TEasyCURLInfo*)data;
assert(pEasyCURLInfo != NULL);
unsigned int nCURLID = pEasyCURLInfo->nCURLID;
CGatherMemoryMan* pMemoryMan = pEasyCURLInfo->pMemoryMan;
assert(pMemoryMan != NULL);
uint32_t nWriteSize = pMemoryMan->PutData(nCURLID, (char*)ptr,
size*nmemb);
return nWriteSize;
}
CPageGather::CPageGather()
{
m_pGatherStateMan = NULL;
m_pGatherRequestMan = NULL;
m_pGatherMemoryMan = NULL;
m_pGatherResultMan = NULL;
m_pMultiCURL = NULL;
m_pEasyCURLInfoArray = NULL;
m_nReadRequestCount = 0;
m_nOutputResultCount = 0;
if(m_nGlobalInitCount == 0)
{
if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK)
{
printf("curl_global_init() failed\n");
_exit(-1);
}
}
m_nGlobalInitCount++;
}
CPageGather::~CPageGather()
{
Exit();
m_nGlobalInitCount--;
if(m_nGlobalInitCount == 0)
curl_global_cleanup();
}
void CPageGather::Exit()
{
if (m_pGatherMemoryMan != NULL)
{
delete m_pGatherMemoryMan;
m_pGatherMemoryMan = NULL;
}
if (m_pGatherStateMan != NULL)
{
delete m_pGatherStateMan;
m_pGatherStateMan = NULL;
}
if (m_pGatherResultMan != NULL)
{
delete m_pGatherResultMan;
m_pGatherResultMan = NULL;
}
if (m_pGatherRequestMan != NULL)
{
delete m_pGatherRequestMan;
m_pGatherRequestMan = NULL;
}
if (m_pEasyCURLInfoArray != NULL)
{
for(uint32_t i = 0; i < m_nSocketNum; i++)
{
curl_easy_cleanup(m_pEasyCURLInfoArray[i].pEasyCURL);
}
delete[] m_pEasyCURLInfoArray;
m_pEasyCURLInfoArray = NULL;
}
while(!m_qFreeEasyCURLID.empty())
m_qFreeEasyCURLID.pop();
if (m_pMultiCURL != NULL)
{
curl_multi_cleanup(m_pMultiCURL);
m_pMultiCURL = NULL;
}
}
bool CPageGather::Init(uint32_t nSocketNum,
bool bRemoveHeader,
uint32_t nMemBlocks,
uint32_t nBlockSize)
{
//some initializations here...
//init a multi curl: m_pMultiCURL
m_pMultiCURL = curl_multi_init();
if(m_pMultiCURL == NULL)
{
delete m_pGatherMemoryMan;
m_pGatherMemoryMan = NULL;
return false;
}
//init m_pEasyCURLArray, m_qFreeEasyCURLID
m_pEasyCURLInfoArray = new TEasyCURLInfo[m_nSocketNum];
assert(m_pEasyCURLInfoArray != NULL);
for (uint32_t i=0; i<m_nSocketNum; i++)
{
//init an easy curl
CURL* pEasyCURL = curl_easy_init();
if (pEasyCURL == NULL)
{
printf("curl_easy_init() failed\n");
return false;
}
//set the ID for the easy curl
uint32_t nCURLID = i;
//set values of m_pEasyCURLArray[i]
m_pEasyCURLInfoArray[i].nCURLID = nCURLID;
m_pEasyCURLInfoArray[i].pEasyCURL = pEasyCURL;
m_pEasyCURLInfoArray[i].pMemoryMan = m_pGatherMemoryMan;
//add the easy curl into the free curl queue
m_qFreeEasyCURLID.push(nCURLID);
//set options for the easy curl
CURLcode rc = CURLE_OK;
if(!bRemoveHeader)
{
rc = curl_easy_setopt(pEasyCURL, CURLOPT_HEADER, 1);
assert(rc == CURLE_OK);
}
rc = curl_easy_setopt(pEasyCURL, CURLOPT_AUTOREFERER, 1);
rc = curl_easy_setopt(pEasyCURL, CURLOPT_FOLLOWLOCATION, 1);
rc = curl_easy_setopt(pEasyCURL, CURLOPT_MAXREDIRS, 10);
rc = curl_easy_setopt(pEasyCURL, CURLOPT_WRITEDATA,
(void*)&m_pEasyCURLInfoArray[i]);
rc = curl_easy_setopt(pEasyCURL, CURLOPT_WRITEFUNCTION,
WriteDataCallback);
#ifdef HAVE_LIBZ
rc = curl_easy_setopt(pEasyCURL, CURLOPT_ENCODING, "gzip, deflate");
#endif
}
return true;
}
bool CPageGather::Start(const CPageRequest *pstPageReq, uint32_t nCount)
{
m_pGatherRequestMan->AddRequests(pstPageReq,nCount);
m_pGatherStateMan->SetGatherState(STATE_START);
DEFINE_THREAD(t);
if (FAILED_THREAD(BEGIN_THREAD(t, GatherCoreThread, (void*)this)))
{
m_pGatherRequestMan->Clear();
m_pGatherStateMan->SetGatherState(STATE_NOT_START);
return false;
}
return true;
}
void CPageGather::Stop()
{
TGatherState iState = m_pGatherStateMan->GetGatherState();
assert(iState != STATE_USER_SEND_STOP);
if (iState == STATE_ALREADY_STOP)
{
return;
}
while (!m_pGatherStateMan->IsAlreadyStop())
{
m_pGatherStateMan->SetGatherState(STATE_USER_SEND_STOP);
MY_SLEEP(10);
}
}
int CPageGather::AddRequests(const CPageRequest *pstPageReq, uint32_t
nCount)
{
assert(m_pGatherRequestMan != NULL);
return m_pGatherRequestMan->AddRequests(pstPageReq,nCount);
}
GATHER_RESULT* CPageGather::FetchGatherResult(void)
{
assert(m_pGatherResultMan != NULL);
return m_pGatherResultMan->FetchGatherResult();
}
void CPageGather::DestroyResult(GATHER_RESULT* pGatherResult)
{
assert(m_pGatherResultMan != NULL);
m_pGatherResultMan->DeleteGatherResult(pGatherResult);
}
void CPageGather::GatherCore(void)
{
DispatchGatherRequests();
int nStillRunnings = 0;
while(CURLM_CALL_MULTI_PERFORM ==
curl_multi_perform(m_pMultiCURL, &nStillRunnings));
while(!m_pGatherStateMan->IsUserStop())
{
nStillRunnings = FdsetSelect();
ProcessFinishedReqs();
DispatchGatherRequests();
_sleep(10);
}
m_pGatherStateMan->SetGatherState(STATE_ALREADY_STOP);
}
void CPageGather::DispatchGatherRequests(void)
{
while(!m_qFreeEasyCURLID.empty())
{
//fetch a request, if no requests availabe, return
const CPageRequest* pRequest = m_pGatherRequestMan->FetchRequest();
if(pRequest == NULL) return;
//fetch a free easy curl from the queue
unsigned int nCURLID = m_qFreeEasyCURLID.front();
m_qFreeEasyCURLID.pop();
//create private info passed to the easy curl
TRequestInfo *pRequestInfo = new TRequestInfo;
assert(pRequestInfo != NULL);
pRequestInfo->nCURLID = nCURLID;
pRequestInfo->pRequest = pRequest;
//set options for the easy curl
CURL* pEasyCURL = m_pEasyCURLInfoArray[nCURLID].pEasyCURL;
assert(pEasyCURL != NULL);
CURLcode rc = CURLE_OK;
rc = curl_easy_setopt(pEasyCURL, CURLOPT_URL,
pRequest->m_sUrl.c_str());
assert(rc == CURLE_OK);
rc = curl_easy_setopt(pEasyCURL, CURLOPT_PRIVATE, (void*)pRequestInfo);
assert(rc == CURLE_OK);
//add the easy curl to the multi curl
CURLMcode mc = CURLM_OK;
mc = curl_multi_add_handle(m_pMultiCURL, pEasyCURL);
assert(mc == CURLM_OK);
//increace the request count read
m_nReadRequestCount++;
}
}
int CPageGather::FdsetSelect(void)
{
assert(m_pMultiCURL != NULL);
int nStillRunnings = -1;
struct timeval tTimeout;
tTimeout.tv_sec = 0;
tTimeout.tv_usec = 20;
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);
//fdset & select
int maxfd = 0;
CURLMcode nRetCode = curl_multi_fdset(m_pMultiCURL, &fdread, &fdwrite,
&fdexcep, &maxfd);
assert(nRetCode == CURLE_OK);
if(maxfd > -1)
{
int rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &tTimeout);
switch(rc)
{
case -1:
//select error
fprintf(stderr, "select() returns error, this is badness\n");
break;
case 0:
//timeout
break;
default:
//readable/writable sockets
while(CURLM_CALL_MULTI_PERFORM ==
curl_multi_perform(m_pMultiCURL, &nStillRunnings));
break;
}
}
return nStillRunnings;
}
void CPageGather::ProcessFinishedReqs(void)
{
CURLMsg *pCURLMsg = NULL;
assert(m_pMultiCURL != NULL);
int nLeftMsgs = 0;
while ((pCURLMsg = curl_multi_info_read(m_pMultiCURL, &nLeftMsgs)))
{
if (pCURLMsg->msg == CURLMSG_DONE)
{
CURLcode nRetCode = pCURLMsg->data.result;
CURL *pEasyCURL = pCURLMsg->easy_handle;
assert(pEasyCURL != NULL);
//get TRequestInfo*
TRequestInfo* pRequestInfo = NULL;
curl_easy_getinfo(pEasyCURL, CURLINFO_PRIVATE, (char*)&pRequestInfo);
assert(pRequestInfo != NULL);
const CPageRequest* pRequest = pRequestInfo->pRequest;
unsigned int nCURLID = pRequestInfo->nCURLID;
delete pRequestInfo;
pRequestInfo = NULL;
CPageRecord* pResult = new CPageRecord();
assert(pResult != NULL);
pResult->m_pRequest = pRequest;
pResult->m_nTimeStamp = time(NULL);
pResult->m_nRetCode = nRetCode;
pResult->m_sRetMsg = curl_easy_strerror(nRetCode);
if(nRetCode == CURLE_OK)
{
char* sContentType = NULL;
CResponseInfo *pInfo = new CResponseInfo();
assert(pInfo != NULL);
CURLcode rc = CURLE_OK;
rc = curl_easy_getinfo(pEasyCURL, CURLINFO_RESPONSE_CODE,
&pInfo->m_nHttpCode);
assert(rc == CURLE_OK);
rc = curl_easy_getinfo(pEasyCURL, CURLINFO_TOTAL_TIME,
&pInfo->m_dbTransferSecs);
assert(rc == CURLE_OK);
rc = curl_easy_getinfo(pEasyCURL, CURLINFO_FILETIME,
&pInfo->m_nFileTime);
assert(rc == CURLE_OK);
rc = curl_easy_getinfo(pEasyCURL, CURLINFO_CONTENT_TYPE,
&sContentType);
assert(rc == CURLE_OK);
pInfo->m_sContentType = (sContentType!=NULL?sContentType:"");
char* pcURL = NULL;
rc = curl_easy_getinfo(pEasyCURL, CURLINFO_EFFECTIVE_URL, &pcURL);
assert(rc == CURLE_OK);
pInfo->m_sEffectiveURL = pcURL;
pResult->m_pResponseInfo = pInfo;
assert(m_pGatherMemoryMan != NULL);
char* pcData = NULL;
uint32_t nDataLen = 0;
if(m_pGatherMemoryMan->GetData(nCURLID, pcData, nDataLen))
{
pResult->m_pcData = pcData;
pResult->m_nDataLength = nDataLen;
}
}
m_pGatherResultMan->AddGatherResult(pResult);
m_nOutputResultCount++;
m_pGatherMemoryMan->FreeData(nCURLID);
CURLMcode mc = CURLM_OK;
mc = curl_multi_remove_handle(m_pMultiCURL, pEasyCURL);
assert(mc == CURLM_OK);
m_qFreeEasyCURLID.push(nCURLID);
}
}
}
----------------------------------------------------------------------
Comment By: Daniel Stenberg (bagder)
Date: 2007-11-18 09:59
Message:
Logged In: YES
user_id=1110
Originator: NO
Can you please tell us how to repeat this problem? Is there a recipe we
can follow? Is there a source code example you use to get this problem?
That code hasn't been modified in a long time and thus is used like that
by millions of people with no problems, why I rather think the error is in
your code...
----------------------------------------------------------------------
You can respond by visiting:
https://sourceforge.net/tracker/?func=detail&atid=100976&aid=1833734&group_id=976
Received on 2007-11-18