Curl client using threads in c gives random behavior?

CrydaySicaics

New Member
We are developing a asynchronous server for a specific project using mongoose. It takes a request, gives an immediate response, does all the parsing it needs and then responds back on a URL that is passed in the original request.The request reception part is flawless. The response is another story though.cant place the whole program here (propriety issues), but I have been able to make a replica such that the issue is demonstrable.\[code\]/* * xmlcrlth.c * * Created on: Jun 28, 2012 * Author: mfaraz */#include <pthread.h>#include <string.h>#include <stdio.h>#include <time.h>#include <curl/curl.h>#include <libxml2/libxml/xmlreader.h>#include <libxml2/libxml/encoding.h>#include <libxml2/libxml/xmlwriter.h>#define MAX_DATA_LEN (140)#define MAX_XML_LEN (1024)#define MAX_THREAD_STACK (1024 * 1024)//#define MY_ENCODING "ISO-8859-1"#define MY_ENCODING "UTF-8"#define DEFAULT_THREADS 25//typedefstruct responseInfo { pthread_t thread_id; /* ID returned by pthread_create() */ int urlLength; /* The Length of the URL */ int xmlLength; /* The Length of the XML */ char theXML[MAX_XML_LEN]; /* The XML to post */ char theURL[MAX_DATA_LEN]; /* The URL to post to */};static void *threadCurl(void *newResponse) { pthread_detach(pthread_self()); struct responseInfo *thisReponse = (struct responseInfo *) newResponse; char thisXML[MAX_XML_LEN], thisURL[MAX_DATA_LEN]; CURL *curlResponse; /* cURL variable to perform a Response */ CURLcode curlResCode; /* cURL Response Code */ struct curl_slist *headList = NULL; int urlLength = strlen(thisReponse->theURL); int xmlLength = strlen(thisReponse->theXML); printf("Received XML (%d vs %d bytes) using ThreadID %lu\n%s \nto URL (%d vs %d bytes) %s\n", xmlLength, thisReponse->xmlLength, thisReponse->thread_id, thisReponse->theXML, urlLength, thisReponse->urlLength, thisReponse->theURL);// if (urlLength != thisReponse->urlLength) strncpy(thisURL, thisReponse->theURL, thisReponse->urlLength);// if (xmlLength != thisReponse->xmlLength) strncpy(thisXML, thisReponse->theXML, thisReponse->xmlLength); /*FILE *filePtr; char fileName[MAX_DATA_LEN] = ""; sprintf(fileName, "%lu", pthread_self()); filePtr = fopen(fileName, "a+"); fprintf(filePtr, "-------------------------\n"); fprintf(filePtr, "ThreadID: %s\n", fileName); fprintf(filePtr, "OurlLength: %d\tCurlLength: %d\n", thisReponse->urlLength, urlLength); fprintf(filePtr, "OxmlLength: %d\tCxmlLength: %d\n\n", thisReponse->xmlLength, xmlLength); fprintf(filePtr, "OrigURL: %s\n", thisReponse->theURL); fprintf(filePtr, "OrigXML: %s\n", thisReponse->theXML); fprintf(filePtr, "NewURL: %s\n", thisURL); fprintf(filePtr, "NewXML: %s\n", thisXML); fclose(filePtr);//*/ urlLength = strlen(thisURL); xmlLength = strlen(thisXML); printf("Sending XML (%d bytes) using ThreadID %lu\n%s \nto URL (%d bytes) %s\n", xmlLength, thisReponse->thread_id, thisXML, urlLength, thisURL); headList = curl_slist_append(headList, "Content-Type: text/xml"); curlResponse = curl_easy_init(); if (curlResponse) { curl_easy_setopt(curlResponse, CURLOPT_URL, thisURL); curl_easy_setopt(curlResponse, CURLOPT_HTTPHEADER, headList);// curl_easy_setopt(curlResponse, CURLOPT_POSTFIELDS, xmlResp); curl_easy_setopt(curlResponse, CURLOPT_POSTFIELDSIZE, thisReponse->xmlLength); curl_easy_setopt(curlResponse, CURLOPT_COPYPOSTFIELDS, thisXML); curl_easy_setopt(curlResponse, CURLOPT_CONNECTTIMEOUT, 10); curl_easy_setopt(curlResponse, CURLOPT_TIMEOUT, 30); curl_easy_setopt(curlResponse, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(curlResponse, CURLOPT_FRESH_CONNECT, 1); curl_easy_setopt(curlResponse, CURLOPT_FORBID_REUSE, 1); curlResCode = curl_easy_perform(curlResponse); if (curlResCode) printf("Curl Failed with status: %s!\n", curl_easy_strerror(curlResCode)); curl_easy_cleanup(curlResponse); } else { printf("Curl Init Failed!\n"); curlResCode = CURLE_FAILED_INIT; } curl_slist_free_all(headList); free(thisReponse); pthread_exit(NULL);// return (int)curlResCode;}char *getXML(int failCode, char *failDesc) { int rc; xmlTextWriterPtr writer; xmlBufferPtr buf;// xmlChar *tmp; static char xmlResp[1024]; xmlResp[0] = '\0'; /* Create a new XML buffer, to which the XML document will be written */ buf = xmlBufferCreate(); if (buf == NULL) printf("MTU_smac: Error creating the xml buffer\n"); /* Create a new XmlWriter for memory, with no compression. * Remark: there is no compression for this kind of xmlTextWriter */ writer = xmlNewTextWriterMemory(buf, 0); if (writer == NULL) printf("MTU_smac: Error creating the xml writer\n"); /* Start the document with the xml default for the version, * encoding ISO 8859-1 and the default for the standalone * declaration. */ rc = xmlTextWriterStartDocument(writer, NULL, MY_ENCODING, NULL); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterStartDocument\n"); /* Start an element named "svc_result". Since thist is the first * element, this will be the root element of the document. */ rc = xmlTextWriterStartElement(writer, (xmlChar *)"svc_result"); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterStartElement\n"); /* Start an element named "sli_rep" as child of svc_result. */ rc = xmlTextWriterStartElement(writer, (xmlChar *)"sli_rep"); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterStartElement\n"); /* Add an attribute with name "version" and value "1.0" to sli_rep. */ rc = xmlTextWriterWriteAttribute(writer, (xmlChar *)"version", (xmlChar *)"3.0.0"); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterWriteAttribute\n"); /* Start an element named "pos" as child of sli_rep. */ rc = xmlTextWriterStartElement(writer, (xmlChar *)"pos"); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterStartElement\n"); /* Write an element named "poserr" as child of pos. */ rc = xmlTextWriterStartElement(writer, (xmlChar *)"poserr"); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterStartElement\n"); /* Write an element named "time" as child of poserr. */ rc = xmlTextWriterWriteElement(writer, (xmlChar *)"time", (xmlChar *)"Time will Come here"); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterWriteFormatElement\n"); /* Add an attribute with name "utc" and value "+0500" to time. */ rc = xmlTextWriterWriteAttribute(writer, (xmlChar *)"utc", (xmlChar *)"+0500"); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterWriteAttribute for utc\n"); /* Write an element named "result" as child of poserr. */ rc = xmlTextWriterWriteFormatElement(writer, (xmlChar *)"result", "%s", failDesc); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterWriteFormatElement\n"); /* Add an attribute with name "utc" and value "+0500" to time. */ rc = xmlTextWriterWriteAttribute(writer, (xmlChar *)"resid", (xmlChar *)failCode); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterWriteAttribute for resid\n"); /* Close the element named poserr. */ rc = xmlTextWriterEndElement(writer); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterEndElement\n"); /* Close the element named pos. */ rc = xmlTextWriterEndElement(writer); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterEndElement\n"); /* Start an element named "extra" as child of sli_rep. */ rc = xmlTextWriterStartElement(writer, (xmlChar *)"extra"); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterStartElement\n"); /* Write an element named "resp_status" as child of extra. */ rc = xmlTextWriterWriteFormatElement(writer, (xmlChar *)"resp_status", "%d", failCode); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterWriteFormatElement\n"); /* Here we could close the elements sli_rep and svc_result using the * function xmlTextWriterEndElement, but since we do not want to * write any other elements, we simply call xmlTextWriterEndDocument, * which will do all the work. */ rc = xmlTextWriterEndDocument(writer); if (rc < 0) printf("MTU_smac: Error at xmlTextWriterEndDocument\n"); xmlFreeTextWriter(writer);// printf("%s\n", (const char *) buf->content); sprintf(xmlResp, "%s", (const char *) buf->content); xmlBufferFree(buf); return xmlResp;}int postXMLResponse(char *xmlResp, char *theURL) { int urlLength = strlen(theURL); if (urlLength == 0) return 0; // No URL...no Tension...! struct responseInfo *newResponse; pthread_attr_t theAttribs; int threadPtr; // Init the threading threadPtr = pthread_attr_init(&theAttribs); if (threadPtr) return threadPtr; else printf("Thread Initialized!\n"); // Set the Stack size. threadPtr = pthread_attr_setstacksize(&theAttribs, MAX_THREAD_STACK); if (threadPtr) return threadPtr; else printf("Thread Stack Size set!\n"); // Set the Thread as Detachable. threadPtr = pthread_attr_setdetachstate(&theAttribs, PTHREAD_CREATE_DETACHED); if (threadPtr) return threadPtr; // Allocate memory for the responseInfo newResponse = malloc(sizeof(struct responseInfo)); if (newResponse == NULL) return -1; else printf("Structure MALLOC'ed!\n"); int xmlLength = strlen(xmlResp); int xmlLength2 = xmlLength;//293; newResponse->urlLength = urlLength; newResponse->xmlLength = xmlLength; strncpy(newResponse->theURL, theURL, urlLength); strncpy(newResponse->theXML, xmlResp, xmlLength2); printf("Threading Send XML (%d bytes)\n%s \nto URL (%d bytes) %s\n", xmlLength, newResponse->theXML, urlLength, newResponse->theURL); threadPtr = pthread_create(&newResponse->thread_id, &theAttribs, &threadCurl, newResponse); if (threadPtr) return threadPtr; else printf("Thread Created with ThreadID %lu!\n", newResponse->thread_id); /*FILE *filePtr; char fileName[MAX_DATA_LEN] = ""; sprintf(fileName, "%lu", newResponse->thread_id); filePtr = fopen(fileName, "a"); fprintf(filePtr, "ThreadID: %s\n", fileName); fprintf(filePtr, "urlLength: %d\n", newResponse->urlLength); fprintf(filePtr, "xmlLength: %d\n", newResponse->xmlLength); fprintf(filePtr, "URL: %s\n", newResponse->theURL); fprintf(filePtr, "XML: %s", newResponse->theXML); fclose(filePtr);//*/ threadPtr = pthread_attr_destroy(&theAttribs); if (threadPtr) return threadPtr; else printf("Thread Attributes!\n"); return 0;}int main(int argc, char *argv[]) { long int iLoop, iMaxCount; curl_global_init(CURL_GLOBAL_ALL); iMaxCount = DEFAULT_THREADS; if (argc > 1) {// printf("Showing Arguments: -\n"); for (iLoop = 1 ; iLoop < argc ; iLoop++) printf("%lu = %s\n", iLoop + 1, argv[iLoop]); iMaxCount = strtol(argv[1], NULL, 10); } for (iLoop = 0 ; iLoop < iMaxCount ; iLoop++) { postXMLResponse(getXML(iLoop, "All of your base are belong to us!"), "http://localhost:80/response.php"); } sleep(3); return 0;}\[/code\]You will need to set "xml2", "curl" and "pthread" for libraries and "-pthread" for the linker. Depending on your setup, you might also need to specify the actual folder for the libxml library.When you run the program, it will try to generate 25 threads. The first argument can change that to be whatever number suits you for testing. In my tests, even a 5, results in only 3 requests landing on the webserver. Even out of those 3, one had a corrupt URL and one had a corrupt XML.I know I am missing something for waiting for the threads to end (cant figure that out, as the main server is not going to stop).Somebody point something wrong here!
 
Back
Top