Curl запрос в потоке двойной бесплатно - PullRequest
0 голосов
/ 15 марта 2019

У меня проблема с проблемой, когда я запускаю N потоков, и в каждом потоке я делаю запрос, используя ответ на чтение curl на char*. Иногда , когда я освобождаю ответ, у меня появляется ошибка double free or corruption (fasttop). Код ниже:

static void* crawler_threadHandler(void* _arg) 
{
    size_t thisId = (size_t)_arg;
    crawler_thread* thisThread = &crawler.threads[thisId];
    CURL *curl = curl_easy_init();

    if (crawler.prepareRequestCommon != NULL)
    {
        crawler.prepareRequestCommon(curl);
    }

    while(thisThread->stopRequest == false)
    {
        crawler_runRequest(curl);

        sleep(1);
    }

    curl_easy_cleanup(curl);
    thisThread->isRunning = false;

    return NULL;
}

static void crawler_runRequest(CURL* curl)
{
    CURLcode res;
    struct curl_slist* headers = NULL;
    char* response = (char*) malloc(1);

    if (crawler.prepareRequestEach != NULL)
    {
        crawler.prepareRequestEach(curl, headers);
    }

    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, crawler_reponseWriteCallback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*) response);
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    res = curl_easy_perform(curl);
    curl_slist_free_all(headers);

    if(res != CURLE_OK)
    {
        fprintf(
            stderr, 
            "curl_easy_perform() failed: %s\n",
            curl_easy_strerror(res)
        );
    }
    else
    {
        if (crawler.parseResponse != NULL)
        {
            crawler.parseResponse(response);
        }
    }

    if (response != NULL)
    {
        free(response); //Here is crash
    }
}

static size_t crawler_reponseWriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
    size_t realsize = size * nmemb;

    userp = realloc(userp, realsize + 1);

    if (userp == NULL)
    {
        fprintf(
            stderr, 
            "No space left in head for allocate response, bytes: %zu\n", 
            realsize
        );
        realsize = 0;
    }
    else
    {
        char terminateNull = '\0';
        memcpy(userp, contents, realsize);
        memcpy(userp + realsize, &terminateNull, 1);
    }

    return realsize;
}

Функция crawler_threadHandler - это вызов обработчика pthread

errno = pthread_create(&thread.pthread, NULL, crawler_threadHandler, (void*) i);

Я имею в виду иногда сбой: при запуске 3 потоков происходит сбой 1 или 2 раза.

Пожалуйста, помогите, я понятия не имею, где ошибка.

Редактировать: Работает после изменений:

//crawler_runRequest
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*) &response);

...

//crawler_reponseWriteCallback
void** responsePtr = userp;
*responsePtr = realloc(*responsePtr, realsize + 1);

...

memcpy(*responsePtr, contents, realsize);
memcpy(*responsePtr + realsize, &terminateNull, 1);
...