Hi Eric, Libcurl is not threadsafe. Study the multi interface and run everything curl on a single thread instead. It takes a bit more work but saves resources.
Erik -----Original Message----- From: curl-library <[email protected]> On Behalf Of erbenton Sent: dinsdag 31 juli 2018 09:28 To: [email protected] Subject: segfault when using libcurl in thread but ok when used non threaded 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 ------------------------------------------------------------------- Unsubscribe: https://cool.haxx.se/list/listinfo/curl-library Etiquette: https://curl.haxx.se/mail/etiquette.html
