cURL / Mailing Lists / curl-library / Single Mail

curl-library

Is Curl_resolve thread safe?

From: Nigel Horne <njh_at_bandsman.co.uk>
Date: Wed, 18 Aug 2004 22:32:35 +0100

Is Curl_resolve thread safe()?

Valgrind reports errors such as this on every call.
The unititialised value is of course more serious than the mutex is not
locked error.

This is on Fedora Core 1 Linux/x86.

--snip--
==29426== Thread 3:
==29426== pthread_mutex_unlock: mutex is not locked
==29426== at 0x37CF8B: __pthread_mutex_unlock (vg_libpthread.c:993)
==29426== by 0x4B415B: _IO_fclose@@GLIBC_2.1 (in /lib/libc-2.3.2.so)
==29426== by 0x544DD8: do_init (in /lib/libc-2.3.2.so)
==29426== by 0x37E07C: __pthread_once (vg_libpthread.c:1551)
==29426== by 0x544719: _res_hconf_init (in /lib/libc-2.3.2.so)
==29426== by 0x548B12: gethostbyaddr_r@@GLIBC_2.1.2 (in
/lib/libc-2.3.2.so)
==29426== by 0x51B77A: gaih_inet (in /lib/libc-2.3.2.so)
==29426== by 0x51C923: __GI_getaddrinfo (in /lib/libc-2.3.2.so)
==29426== by 0xF16CA6: (within /usr/lib/libcurl.so.2.0.2)
==29426== by 0xF16A4F: Curl_resolv (in /usr/lib/libcurl.so.2.0.2)
==29426== by 0xF22801: (within /usr/lib/libcurl.so.2.0.2)
==29426== by 0xF23A9B: Curl_connect (in /usr/lib/libcurl.so.2.0.2)
==29426== by 0xF2E52C: Curl_perform (in /usr/lib/libcurl.so.2.0.2)
==29426== by 0xF2E9E0: curl_easy_perform (in /usr/lib/libcurl.so.2.0.2)
==29426== by 0xB88B81: getURL (mbox.c:2550)
==29426== by 0x37C6E9: thread_wrapper (vg_libpthread.c:667)
==29426== by 0x143ABF: ??? (vg_scheduler.c:2142)
==29426==
==29426== Thread 3:
==29426== Use of uninitialised value of size 4
==29426== at 0x5489D6: gethostbyaddr_r@@GLIBC_2.1.2 (in
/lib/libc-2.3.2.so)
==29426== by 0x51B77A: gaih_inet (in /lib/libc-2.3.2.so)
==29426== by 0x51C923: __GI_getaddrinfo (in /lib/libc-2.3.2.so)
==29426== by 0xF16CA6: (within /usr/lib/libcurl.so.2.0.2)
==29426== by 0xF16A4F: Curl_resolv (in /usr/lib/libcurl.so.2.0.2)
==29426== by 0xF22801: (within /usr/lib/libcurl.so.2.0.2)
==29426== by 0xF23A9B: Curl_connect (in /usr/lib/libcurl.so.2.0.2)
==29426== by 0xF2E52C: Curl_perform (in /usr/lib/libcurl.so.2.0.2)
==29426== by 0xF2E9E0: curl_easy_perform (in /usr/lib/libcurl.so.2.0.2)
==29426== by 0xB88B81: getURL (mbox.c:2550)
==29426== by 0x37C6E9: thread_wrapper (vg_libpthread.c:667)
==29426== by 0x143ABF: ??? (vg_scheduler.c:2142)
--snip--

With this code:
static void *
getURL(void *a)
{
        char *fout;
        CURL *curl;
        FILE *fp;
        struct curl_slist *headers;
        static int initialised = 0;
        static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
        struct arg *arg = (struct arg *)a;
        const char *url = arg->url;
        const char *dir = arg->dir;
        const char *filename = arg->filename;

        pthread_mutex_lock(&init_mutex);
        if(!initialised) {
                if(curl_global_init(CURL_GLOBAL_NOTHING) != 0) {
                        pthread_mutex_unlock(&init_mutex);
                        return NULL;
                }
                initialised = 1;
        }

        pthread_mutex_unlock(&init_mutex);

        curl = curl_easy_init();
        if(curl == NULL)
                return NULL;

        (void)curl_easy_setopt(curl, CURLOPT_USERAGENT,
"www.bandsman.co.uk");

        if(curl_easy_setopt(curl, CURLOPT_URL, url) != 0)
                return NULL;

        fout = cli_malloc(strlen(dir) + strlen(filename) + 2);

        if(fout == NULL) {
                curl_easy_cleanup(curl);
                return NULL;
        }

        sprintf(fout, "%s/%s", dir, filename);

        fp = fopen(fout, "w");

        if(fp == NULL) {
                perror(fout);
                free(fout);
                curl_easy_cleanup(curl);
                return NULL;
        }
        if(curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp) != 0) {
                fclose(fp);
                free(fout);
                curl_easy_cleanup(curl);
                return NULL;
        }

        headers = curl_slist_append(NULL, "Pragma:");
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

        /* These should be customisable */
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30);
        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10);
#ifdef CURLOPT_MAXFILESIZE
        curl_easy_setopt(curl, CURLOPT_MAXFILESIZE, 50*1024);
#endif

        curl_easy_setopt(curl, CURLOPT_DNS_USE_GLOBAL_CACHE, 0);
 
        if(curl_easy_perform(curl) != CURLE_OK) {
                cli_warnmsg("URL %s failed to download\n", url);
                unlink(fout);
        }

        fclose(fp);
        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
        free(fout);

        return NULL;
}

-Nigel
Received on 2004-08-18