curl / Mailing Lists / curl-library / Single Mail

curl-library

segfault when using libcurl in thread but ok when used non threaded

From: erbenton <erbenton_at_comcast.net>
Date: Tue, 31 Jul 2018 00:27:56 -0700

openSuse Leap 42.3 x86-64
libcurl version 4, openSuse version 7.37.0-36 and on disk i see
libcurl.so.4.3.0

I have a simple function that downloads an https webpage.
If i call my thread function as you would a non threaded function it
works fine.
If I run it as a thread it works ok for a few iterations then segfaults
at  curl_easy_perform.
I have included a simplified C program that illustrates the problem.
(my guess is attachments are not allowed so the C source is below)
compile it with:
     gcc -O0 -g3 test.c -o test -lpthread -lcurl
and to run without thread its "./test X" (any parameter is ok, it only
counts the number of parameters to make its decision)
and to run with threads dont pass any parameters: "./test"

Thanks
Eric

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>

#include <curl/curl.h>

pthread_t threadIDs[200];
char ebuf[512]={0}; // for errno msgs, could be a lot smaller but for
now 1/2k is fine

pthread_t start_thread();
void *test_thread(void *info);

//---------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------

int main(int argc, char **argv)
{
int i, r;

         if(0!=curl_global_init(CURL_GLOBAL_ALL)) {
             printf("Curl globasl Inoit failed\n");
             exit(0);
         }

         if(argc>1) { // call thread routine as an ordinary function call

             for(r=0; r<700; r++) {
                 printf("Begin test run #%d\n", r);
                 test_thread(&i);
                 printf("end test run #%d\n", r);
             }

         } else { // run it as a pthread

             for(r=0; r<700; r++) {
                 printf("Begin test run #%d\n", r);

                 for(i=0; i<10; i++)
                     threadIDs[i] = start_thread();
                 printf("All test threads started\n");

                 for(i=0; i<10; i++)
                     pthread_join(threadIDs[i], NULL);
                 printf("All test threads ended\n");
                 printf("end test run #%d\n", r);
             } // end for r

         } // end if/else

        curl_global_cleanup();

return 0;
}
//---------------------------------------------------------------------------------------------

pthread_t start_thread(void)
{
pthread_attr_t ThreadAttr;
pthread_t      Thread_id;
int            err;

   pthread_attr_init(&ThreadAttr);
   pthread_attr_setdetachstate( &ThreadAttr, PTHREAD_CREATE_JOINABLE );
   errno = 0;
   err = pthread_create(&Thread_id, &ThreadAttr, &test_thread, NULL);

   pthread_attr_destroy(&ThreadAttr);

   if(err != 0)    {

         switch(err)
         {
             case EAGAIN:
                 printf("The system lacked the necessary resources to
create\n");
                 printf("another thread, or the system-imposed limit on
the total\n");
                 printf("number of threads in a process
PTHREAD_THREADS_MAX would be exceeded.\n");
                 break;
             case EINVAL:
                 printf("The value specified by attr is invalid.\n");
                 break;
             case EPERM:
                 printf("The caller does not have appropriate permission
to set the required\n");
                 printf("scheduling parameters or scheduling policy.\n");
                 break;
             default:
                 printf("Some weird error code returned from
pthread_create\n");
                 break;
         }
         printf("Error Code 0x%08X %s: pthread failed to start\n", err,
strerror_r(errno, ebuf, sizeof(ebuf)));
         return -1; // return negative thread id

     } // end if err

return Thread_id;
}
//---------------------------------------------------------------------------------------------

void *test_thread(void *info)
{
CURL *curl_handle;
CURLcode res;
char URL[64] = {0};
FILE *out;

     out = fopen("/dev/null", "w");
     strcpy(URL, "https://www.google.com");

     curl_handle = curl_easy_init();
     if(curl_handle) {
        //curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1);
        curl_easy_setopt(curl_handle, CURLOPT_URL, URL);
        curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
        curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0L);
        //curl_easy_setopt(curl_handle, CURLOPT_HTTPGET, 1L);
        curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, out);
        res = curl_easy_perform(curl_handle);
        curl_easy_cleanup(curl_handle);
     }
     if(out) fclose(out);

return (void *)0;
}
//---------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------

-------------------------------------------------------------------
Unsubscribe: https://cool.haxx.se/list/listinfo/curl-library
Etiquette: https://curl.haxx.se/mail/etiquette.html
Received on 2018-07-31