从不同的线程执行curl_multi_perform导致崩溃

时间:2017-01-31 20:17:14

标签: c++ multithreading curl libcurl nghttp2

在我正在进行的项目中,我需要在必要时拨打GET电话和POST电话。 “GET”调用用于创建从服务器到设备的下行通道,以监控云服务器中发生的任何有趣事件。 “POST”调用用于将数据发送到服务器。服务器有一个限制,即只需要与服务器维护单个连接。由于服务器支持HTTP2,我使用“CURLMOPT_MAX_HOST_CONNECTIONS”并将其设置为1,我使CURL使用1连接,我使用CURLMOPT_PIPELINING并将其设置为CURLPIPE_MULTIPLEX,我正在复用传输。问题是在第二个线程上调用“curl_multi_perform”时代码崩溃。

PS:这是我原始代码的一部分,可能无法直接编译/运行。

#include <stdio.h>
#include <string> 
#include <sstream>
#include <curl.h>
#include <pthread.h>


#define EVENTS_URL "https://avs-alexa-na.amazon.com/v20160207/events"
#define DOWNCHANNEL_URL "https://avs-alexa-na.amazon.com/v20160207/directives"

CURLM *multi_handle;
CURL *downchannel_handle;
CURL *eventHttp_handle;

size_t processDownchannelResponse(void *ptr, size_t size, size_t nmemb, void *instance)
{

  printf(" There is downchannel response.");
}

size_t eventResponse(void *ptr, size_t size, size_t nmemb, void *instance)
{
  printf("We got eventResponse");
}
/* The downchannel thread needs to be running always 
, if the transfer is done the connection is closed 
we need to open a new connection and wait for more events*/

void createDownchannel()
{
  int retryCount =0;
  std::string downchURL = DOWNCHANNEL_URL;
  long response_code;
  int runninghandles =0;

downchannel_handle = curl_easy_init();

if(downchannel_handle == NULL){
  printf("createDownchannel : Not able to create curl handle");  
  return  ; 
}



struct curl_slist *header = NULL;
header = curl_slist_append(header, "Host: avs-alexa-na.amazon.com"); 
header = curl_slist_append(header, "TOKEN GOES HERE");

curl_easy_setopt(downchannel_handle, CURLOPT_URL, downchURL.c_str()); 
curl_easy_setopt(downchannel_handle, CURLOPT_SSL_VERIFYPEER, 0L); 
curl_easy_setopt(downchannel_handle, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(downchannel_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE); 
curl_easy_setopt(downchannel_handle, CURLOPT_WRITEFUNCTION, processDownchannelResponse); 
curl_easy_setopt(downchannel_handle, CURLOPT_WRITEDATA, NULL);
curl_easy_setopt(downchannel_handle, CURLOPT_PIPEWAIT, 1L); 

if (header) 
  curl_easy_setopt(downchannel_handle, CURLOPT_HTTPHEADER, header);


if(multi_handle)
/* add the individual easy handle */
  curl_multi_add_handle(multi_handle, downchannel_handle);

mbexitdownchannelthread = 1;

do{
  CURLMcode mc;
  int numfds;
  mc = curl_multi_perform(multi_handle, &runninghandles);
  if(mc != CURLM_OK) {
    fprintf(stderr, "curl_multi failed, code %d.n", mc);
    printf(“a<---curl_multi failed, code %d.n", mc);
    break;
  }
  printf("a<--downchannel while");
// downchannel timeout can be higher  10 seconds
  mc = curl_multi_wait(multi_handle, NULL, 0, 10000, &numfds);
  if(mc != CURLM_OK) {
    fprintf(stderr, "curl_multi failed, code %d.n", mc);
    printf("a<---curl_multi failed, code %d.n", mc);
    break;
  }

}while(!mbexitdownchannelthread);


curl_multi_remove_handle(multi_handle, downchannel_handle);

curl_easy_cleanup(downchannel_handle);

if (header)
  curl_slist_free_all(header);


}

bool getTransferStatus(CURLM *multiHandleInstance,CURL *currentHandle,std::string& contentType,int* http_status_code)
{
//check the status of transfer    CURLcode return_code=0;
  int msgs_left=0;
  CURLMsg *msg=NULL;
  CURL *eh=NULL;
  CURLcode return_code; 

  bool msgTrasferDone = false; 

  while ((msg = curl_multi_info_read(multiHandleInstance, &msgs_left))) 
  {  
    if (msg->msg == CURLMSG_DONE) {
      eh = msg->easy_handle;
      if(currentHandle == eh)
      {
        msgTrasferDone = true;
        return_code = msg->data.result;
        if(return_code!=CURLE_OK) 
        {
//fprintf(stderr, "CURL error code: %d\n", msg->data.result);
          printf("a<--return_code!=CURLE_OK CURL error code: %d\n", msg->data.result);
          continue;
        }  
// Get HTTP status code
        *http_status_code=0;
        char* ch= NULL;
        curl_easy_getinfo(eh, CURLINFO_RESPONSE_CODE, http_status_code);
        printf("a<--CURLINFO_RESPONSE_CODE=%d",*http_status_code);
        curl_easy_getinfo(eh, CURLINFO_CONTENT_TYPE, &ch);
        contentType.clear();
        if(ch!=NULL)
          contentType.append(ch);
      }
    }
  }
  return msgTrasferDone;
}

int eventThread()
{ 
  int still_running = 0;

  std::string contentType;
  int responseCode = 0;
  int numfds = 0; 
  std::string postUrl;
  postUrl.assign(EVENTS_URL);

// init the curl session 
  CURL *eventHttp_handle;
  CURLcode res;
  eventHttp_handle = curl_easy_init();

//assign speech buffer pointer for read callbacks

  curl_easy_setopt(eventHttp_handle, CURLOPT_URL, postUrl.c_str()); 
  curl_easy_setopt(eventHttp_handle, CURLOPT_SSL_VERIFYPEER, 0L); 
  curl_easy_setopt(eventHttp_handle, CURLOPT_SSL_VERIFYHOST, 0L);
  curl_easy_setopt(eventHttp_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE); 

/* wait for pipe connection to confirm */ 
  curl_easy_setopt(eventHttp_handle, CURLOPT_PIPEWAIT, 1L); 

  curl_easy_setopt(eventHttp_handle, CURLOPT_WRITEFUNCTION, eventResponse); 
  curl_easy_setopt(eventHttp_handle, CURLOPT_WRITEDATA, NULL);

  struct curl_slist *header = NULL;
  header = curl_slist_append(header, "Host: avs-alexa-na.amazon.com"); 
  header = curl_slist_append(header, "TOKEN GOES HERE");

  if (header) 
    curl_easy_setopt(eventHttp_handle, CURLOPT_HTTPHEADER, header);

  if (multi_handle) 
    curl_multi_add_handle(multi_handle, eventHttp_handle);


  do 
  {     
    {
      CURLMcode mc;
      int numfds;
      mc = curl_multi_perform(multi_handle, &still_running);
      if(mc != CURLM_OK) {
        fprintf(stderr, "curl_multi failed, code %d.n", mc);
        printf("a<---curl_multi failed, code %d.n", mc);
        break;
      }
      mc = curl_multi_wait(multi_handle, NULL, 0, 1000, &numfds);
      if(mc != CURLM_OK) {
        fprintf(stderr, "curl_multi failed, code %d.n", mc);
        printf("a<---curl_multi failed, code %d.n", mc);
        break;
      }

    }

  }while(!getTransferStatus(multi_handle,eventHttp_handle,contentType,&responseCode));


  if (header)
    curl_slist_free_all(header);

  if (formpost)
  { 
    curl_formfree(formpost); 
    formpost = NULL; 
  } 

  printf("a<-- CURL  HTTP RESP CODE =%d",responseCode);

  curl_multi_remove_handle(multi_handle, eventHttp_handle); 
  curl_easy_cleanup(eventHttp_handle); 
  return 0;
}






int main ()
{
  multi_handle = curl_multi_init();
  curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
  curl_multi_setopt(multi_handle, CURLMOPT_MAX_HOST_CONNECTIONS, 1L);

// create a downchannel thread
  pthread_attr_t attr;
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  int err = pthread_create(&mPostThread, &attr, downchannelThread,NULL);
  pthread_attr_destroy(&attr);

// i am doing some work here //
  sleep(3);

// create a event thread
  pthread_attr_t attr;
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  int err = pthread_create(&mPostThread, &attr, eventThread,NULL);
  pthread_attr_destroy(&attr);
}

0 个答案:

没有答案