Browse Source

vtls: make curl_global_sslset thread-safe

.. and update some docs to explain curl_global_* is now thread-safe.

Follow-up to 23af112 which made curl_global_init/cleanup thread-safe.

Closes https://github.com/curl/curl/pull/9016
Jay Satiro 2 years ago
parent
commit
a8a4abb2ae

+ 5 - 1
docs/libcurl/curl_global_cleanup.3

@@ -36,7 +36,11 @@ This function releases resources acquired by \fIcurl_global_init(3)\fP.
 You should call \fIcurl_global_cleanup(3)\fP once for each call you make to
 \fIcurl_global_init(3)\fP, after you are done using libcurl.
 
-\fBThis function is not thread safe.\fP You must not call it when any other
+This function is thread-safe since libcurl 7.84.0 if
+\fIcurl_version_info(3)\fP has the CURL_VERSION_THREADSAFE feature bit set
+(most platforms).
+
+If this is not thread-safe, you must not call this function when any other
 thread in the program (i.e. a thread sharing the same memory) is running.
 This does not just mean no other thread that is using libcurl. Because
 \fIcurl_global_cleanup(3)\fP calls functions of other libraries that are

+ 1 - 1
docs/libcurl/curl_global_init.3

@@ -47,7 +47,7 @@ value unless you are familiar with it and mean to control internal operations
 of libcurl.
 
 This function is thread-safe since libcurl 7.84.0 if
-\fIcurl_version_info(3)\fP has CURL_VERSION_THREADSAFE feature bit set
+\fIcurl_version_info(3)\fP has the CURL_VERSION_THREADSAFE feature bit set
 (most platforms).
 
 If this is not thread-safe, you must not call this function when any other

+ 5 - 1
docs/libcurl/curl_global_sslset.3

@@ -81,7 +81,11 @@ function again to try to select a different backend.
 The SSL backend can be set only once. If it has already been set, a subsequent
 attempt to change it will result in a \fBCURLSSLSET_TOO_LATE\fP.
 
-\fBThis function is not thread safe.\fP You must not call it when any other
+This function is thread-safe since libcurl 7.84.0 if
+\fIcurl_version_info(3)\fP has the CURL_VERSION_THREADSAFE feature bit set
+(most platforms).
+
+If this is not thread-safe, you must not call this function when any other
 thread in the program (i.e. a thread sharing the same memory) is running.
 This does not just mean no other thread that is using libcurl.
 .SH EXAMPLE

+ 5 - 1
docs/libcurl/libcurl-thread.3

@@ -94,7 +94,11 @@ problem reports on *BSD (at least in the past, they may be working fine these
 days). Some operating systems that are known to have solid and working thread
 support are Linux, Solaris and Windows.
 .IP "curl_global_* functions"
-These functions are not thread safe. If you are using libcurl with multiple
+These functions are thread-safe since libcurl 7.84.0 if
+\fIcurl_version_info(3)\fP has the CURL_VERSION_THREADSAFE feature bit set
+(most platforms).
+
+If these functions are not thread-safe and you are using libcurl with multiple
 threads it is especially important that before use you call
 \fIcurl_global_init(3)\fP or \fIcurl_global_init_mem(3)\fP to explicitly
 initialize the library and its dependents, rather than rely on the "lazy"

+ 16 - 13
docs/libcurl/libcurl.3

@@ -154,28 +154,31 @@ that library that describes the SSL protocol.
 allocate resources (e.g. the memory for the GNU TLS tree mentioned above), so
 the companion function \fIcurl_global_cleanup(3)\fP releases them.
 
-The basic rule for constructing a program that uses libcurl is this: Call
+The global constant functions are thread-safe since libcurl 7.84.0 if
+\fIcurl_version_info(3)\fP has the CURL_VERSION_THREADSAFE feature bit set
+(most platforms). Read \fIlibcurl-thread(3)\fP for thread safety guidelines.
+
+If the global constant functions are \fInot thread safe\fP, then you must
+not call them when any other thread in the program is running. It
+is not good enough that no other thread is using libcurl at the time,
+because these functions internally call similar functions of other
+libraries, and those functions are similarly thread-unsafe. You cannot
+generally know what these libraries are, or whether other threads are
+using them.
+
+If the global constant functions are \fInot thread safe\fP, then the basic rule
+for constructing a program that uses libcurl is this: Call
 \fIcurl_global_init(3)\fP, with a \fICURL_GLOBAL_ALL\fP argument, immediately
 after the program starts, while it is still only one thread and before it uses
 libcurl at all. Call \fIcurl_global_cleanup(3)\fP immediately before the
 program exits, when the program is again only one thread and after its last
 use of libcurl.
 
-You can call both of these multiple times, as long as all calls meet
-these requirements and the number of calls to each is the same.
-
 It is not actually required that the functions be called at the beginning
 and end of the program -- that is just usually the easiest way to do it.
-It \fIis\fP required that the functions be called when no other thread
-in the program is running.
 
-These global constant functions are \fInot thread safe\fP, so you must
-not call them when any other thread in the program is running. It
-is not good enough that no other thread is using libcurl at the time,
-because these functions internally call similar functions of other
-libraries, and those functions are similarly thread-unsafe. You cannot
-generally know what these libraries are, or whether other threads are
-using them.
+You can call both of these multiple times, as long as all calls meet
+these requirements and the number of calls to each is the same.
 
 The global constant situation merits special consideration when the
 code you are writing to use libcurl is not the main program, but rather

+ 17 - 0
lib/easy.c

@@ -315,6 +315,23 @@ void curl_global_cleanup(void)
   global_init_unlock();
 }
 
+/*
+ * curl_global_sslset() globally initializes the SSL backend to use.
+ */
+CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
+                              const curl_ssl_backend ***avail)
+{
+  CURLsslset rc;
+
+  global_init_lock();
+
+  rc = Curl_init_sslset_nolock(id, name, avail);
+
+  global_init_unlock();
+
+  return rc;
+}
+
 /*
  * curl_easy_init() is the external interface to alloc, setup and init an
  * easy handle that is returned. If anything goes wrong, NULL is returned.

+ 6 - 4
lib/vtls/vtls.c

@@ -1456,8 +1456,10 @@ static int multissl_setup(const struct Curl_ssl *backend)
   return 0;
 }
 
-CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
-                              const curl_ssl_backend ***avail)
+/* This function is used to select the SSL backend to use. It is called by
+   curl_global_sslset (easy.c) which uses the global init lock. */
+CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
+                                   const curl_ssl_backend ***avail)
 {
   int i;
 
@@ -1486,8 +1488,8 @@ CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
 }
 
 #else /* USE_SSL */
-CURLsslset curl_global_sslset(curl_sslbackend id, const char *name,
-                              const curl_ssl_backend ***avail)
+CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
+                                   const curl_ssl_backend ***avail)
 {
   (void)id;
   (void)name;

+ 3 - 0
lib/vtls/vtls.h

@@ -125,6 +125,9 @@ struct curl_slist *Curl_none_engines_list(struct Curl_easy *data);
 bool Curl_none_false_start(void);
 bool Curl_ssl_tls13_ciphersuites(void);
 
+CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
+                                   const curl_ssl_backend ***avail);
+
 #include "openssl.h"        /* OpenSSL versions */
 #include "gtls.h"           /* GnuTLS versions */
 #include "nssg.h"           /* NSS versions */