cURL / Mailing Lists / curl-library / Single Mail

curl-library

Multi Thread problem

From: Chirag <chirag_at_cellcloud.com>
Date: Fri, 20 Sep 2002 17:52:41 +0530

Hi,

     I have one function which gets content from the web with CURL by
passing the URL to it. I am attaching the code below.

The problem is that this function is called by a number of threads (15
threads to be precise). The whole code runs fine for some time, but then
when there are say 5 requests at the same time to a same URL, and when it
tries to retrive the content simultaneously, sometime in between i get a
seg_fault. I have put VERBOSE and here is where it gives me a seg_fault
always....By default i am giving a timeout of 60 secs. I dont know what cud
be the problem. I have tried all combination of increasing the timeout from
5 secs to 60 secs. Also i have tried it with 5 threads to 13 threads but the
crash is erratic. As u see from the VERBOSE below....when two or more
threads have simultaneously got the content....my program goes down.

Please throw some light. I am working on Solaris 8.

* Connected to 66.13.8.101 (66.13.8.101)
> GET /servlet/ICC?msisdn=919845114579&message=CRICKET HTTP/1.1
Host: 66.13.8.101:8080
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*

* Connected to 66.13.8.101 (66.13.8.101)
> GET /servlet/ICC?msisdn=919845156838&message=BUZZ%20C HTTP/1.1
Host: 66.13.8.101:8080
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*

* Connection (#0) left alive
---------------> Result of the CURL PERFORM is 0
------>After CURL Perform
* Closing live connection (#0)

The code is below ****************

CURL_MEM get_url_content_from_web(unsigned char * url_to_be_fetched, int
timeout, int answer)
{
   CURL *curl_handle;
   CURLcode res;
   char * http_header=NULL;
   char * http_body=NULL;

   struct MemoryStruct chunk;
   CURL_MEM curl_mem;

   char http[20];
   int status;

    chunk.memory=NULL; /* we expect realloc(NULL, size) to work */
    chunk.size = 0; /* no data at this point */

    printf("URL to be retrieved by CURL is %s\n",url_to_be_fetched);

     // init the curl session
    curl_handle = curl_easy_init();

 // specify URL to get
    curl_easy_setopt(curl_handle, CURLOPT_URL, url_to_be_fetched);
 // Set option for HTTP Headers
 curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, TRUE);
 curl_easy_setopt(curl_handle, CURLOPT_HEADER, TRUE);
 //Set follow-up if the page is redirected
 curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 2);
 //Set conn. timeout
 curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, timeout);
 // WMCB collects the URL content into a buffer
 curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);

    // we pass our 'chunk' struct to the callback function
    curl_easy_setopt(curl_handle, CURLOPT_FILE, (void *)&chunk);

    // get it!
 printf("------>Before CURL Perform\n");
    res = curl_easy_perform(curl_handle);
 printf("---------------> Result of the CURL PERFORM is %d\n",res);
 printf("------>After CURL Perform\n");
 curl_mem.err_no = res;

  if(res != 0)//Could be some CURL error
  {
   chunk.memory = (unsigned char *) malloc (ERROR_SIZE);
   bzero(chunk.memory,ERROR_SIZE);
   strcpy(chunk.memory,curl_error_codes(res));
   chunk.size = strlen(chunk.memory);
   goto END;
  }

 //If no SMS response is asked or the chunk has nothing
 if((answer == 0) || (strlen(chunk.memory) == 0) || (chunk.size == 0))
 {
  chunk.memory = (unsigned char *) malloc (DB_NUM_SIZE);
  bzero(chunk.memory,DB_NUM_SIZE);
  strcpy(chunk.memory,"ok");
  chunk.size = strlen(chunk.memory);
  goto END;
 }

   //printf("Chunk size is %d\nChunk content is
(%s)\n\n",chunk.size,chunk.memory);
 http_header = (char *) malloc (HEADER_SIZE);
 bzero(http_header, HEADER_SIZE);

STRIP_HEAD:
 sscanf(chunk.memory, "%[^\r\n]", http_header);
 printf("#### HTTP HEADER (%s)\n", http_header);

 http_body = (char *)strstr(chunk.memory, "\r\n\r\n");
 if(http_body == NULL) {
  chunk.memory = (unsigned char *) malloc (DB_NUM_SIZE);
  bzero(chunk.memory,DB_NUM_SIZE);
  strcpy(chunk.memory,"ok");
  chunk.size = strlen(chunk.memory);

 } else {

  sscanf(http_header,"%s %d",http,&status);

   printf("Header is %s and status is %d\n",http,status);
  if(status >= 301 && status <= 304) {
    printf("The header status is ########### %d ############\n",status);
   chunk.memory = (unsigned char *) malloc (strlen(http_body)+1);
   bzero(chunk.memory, strlen(http_body)+1);
   strcpy(chunk.memory, http_body+strlen("\r\n\r\n"));
   chunk.size = strlen(chunk.memory);

   goto STRIP_HEAD;
  } else if(status == 200) { //Success
   chunk.memory = (unsigned char *) malloc (strlen(http_body)+1);
   bzero(chunk.memory, strlen(http_body)+1);
   strcpy(chunk.memory, http_body+strlen("\r\n\r\n"));
   chunk.size = strlen(chunk.memory);
   printf("#### HTTP BODY (Chunk) size (%d) and content (%s)\n", chunk.size,
chunk.memory);
   if(chunk.size == 0) {
              chunk.memory = (unsigned char *) malloc (strlen("ok")+1);
              bzero(chunk.memory, strlen("ok")+1);
                 strcpy(chunk.memory,"ok");
                 chunk.size = strlen(chunk.memory);
            }
  } else if(status >= 1 && status <= 52) { //CURL Errors
   chunk.memory = (unsigned char *) malloc (ERROR_SIZE);
   bzero(chunk.memory,ERROR_SIZE);
   strcpy(chunk.memory,curl_error_codes(status));
   chunk.size = strlen(chunk.memory);
  } else {
   chunk.memory = (unsigned char *) malloc (strlen(http_header)+1);
   bzero(chunk.memory,strlen(http_header)+1);
   strcpy(chunk.memory, http_header);
   chunk.size = strlen(chunk.memory);
  }
 }

END:
 printf("Copying chunk.memory and chunk.size\n");
 curl_mem.mems.memory = chunk.memory;
 curl_mem.mems.size = chunk.size;

 //Trying to cleanup curl at the end
  curl_easy_cleanup(curl_handle);
 return(curl_mem);
}

Additional Functions called from above

unsigned char * curl_error_codes(int);

  struct MemoryStruct {
    unsigned char *memory;
    size_t size;
  };

  typedef struct CURL_MEM CURL_MEM;
 struct CURL_MEM {
  int err_no;
  struct MemoryStruct mems;
 };

  size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void
*data)
  {
    register int realsize = size * nmemb;
    struct MemoryStruct *mem = (struct MemoryStruct *)data;

    mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1);
    if (mem->memory) {
     memcpy(&(mem->memory[mem->size]), ptr, realsize);
      mem->size += realsize;
      mem->memory[mem->size] = 0;
   }
    return realsize;
 }

Thank you,
Chirag

-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
Received on 2002-09-20