cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: libcurl and multithreading

From: Bryan Henderson <bryanh_at_giraffe-data.com>
Date: Fri, 23 Dec 2005 22:47:44 +0100

>the easy workaround is to call curl_global_init explicitly,

As stated, that's no workaround. The two threads can still call
curl_global_init() simultaneously. The workaround is to call
curl_global_init() when the program is still just one thread.

This is actually one of the things my global variable elimination is
about. Programs without global variables are much easier to make
thread-safe than program with global variables because it's possible
for two threads to have completely separate memory.

What happens with the two threads doing curl_global_init (or first
curl_easy_init) is that each does this:

  if (!has_been_initialized) {
     initialize();
     has_been_initialize = true;
  }

Two simultaneous threads call initialize(). That means the equivalent
of curl_global_init in any of various underlying libraries gets called
twice simultaneously. Those libraries have the same global variable
disease, and the problem propagates down until some library (gnutls is
one example I know) does this:

  if (!has_been_initialized) {
    global_state_tracker_p = malloc(...);
    has_been_initialized = true;
  }
  ...
  global_state_tracker_p->xxx = yyy;
  ...
  if (global_state_tracker_p->xxx != yyy) {
     printf("Whoa! what happened to my yyy? Crashing...");
  }

(Both threads set global_state_tracker_p; the first to arrive later sees
it magically changed to point somewhere else).

So the manual update should be simply to point out that
curl_global_init() is not thread-safe (but one should expect that
based on its name anyway!). The manual already says not to rely on
the implicit global init in curl_easy_init(). I don't think it needs
any more there.

-- 
Bryan Henderson                                    Phone 408-621-2000
San Jose, California
Received on 2005-12-23