Bryan Henderson turned the 'initialized' variable for curl_global_init()

into a counter, and thus you can now do multiple curl_global_init() and you
are then supposed to do the same amount of calls to curl_global_cleanup().
Bryan also updated the docs accordingly.
This commit is contained in:
Daniel Stenberg 2006-01-15 23:55:53 +00:00
parent 802b2aaf6a
commit 4c35a40858
7 changed files with 162 additions and 31 deletions

View File

@ -6,6 +6,12 @@
Changelog
Daniel (16 January 2006)
- Bryan Henderson turned the 'initialized' variable for curl_global_init()
into a counter, and thus you can now do multiple curl_global_init() and you
are then supposed to do the same amount of calls to curl_global_cleanup().
Bryan has also updated the docs accordingly.
Daniel (13 January 2006)
- Andrew Benham fixed a race condition in the test suite that could cause the
test script to kill all processes in the current process group!

View File

@ -11,7 +11,9 @@ Curl and libcurl 7.15.2
This release includes the following changes:
o
o curl_global_init() and curl_global_cleanup() are now using a refcount so
that it is now legal to call them multiple times. See updated info for
details.
This release includes the following bugfixes:
@ -37,6 +39,6 @@ This release would not have looked like this without help, code, reports and
advice from friends like these:
Dov Murik, Jean Jacques Drouin, Andres Garcia, Yang Tse, Gisle Vanem, Dan
Fandrich, Alexander Lazic, Michael Jahn, Andrew Benham
Fandrich, Alexander Lazic, Michael Jahn, Andrew Benham, Bryan Henderson
Thanks! (and sorry if I forgot to mention someone)

View File

@ -14,12 +14,17 @@ handle that you must use as input to other easy-functions. curl_easy_init
initializes curl and this call \fBMUST\fP have a corresponding call to
\fIcurl_easy_cleanup(3)\fP when the operation is complete.
If you did not already call \fIcurl_global_init(3)\fP, it will be done
automatically with a default setup when you call \fIcurl_easy_init(3)\fP.
If you did not already call \fIcurl_global_init(3)\fP,
\fIcurl_easy_init(3)\fP does it automatically.
This may be lethal in multi-threaded cases, since \fIcurl_global_init(3)\fP is
not thread-safe and must not be called more than once (or from more than one
thread). You are strongly adviced to not rely on this automatic behaviour, but
call \fIcurl_global_init(3)\fP yourself properly.
not thread-safe, and it may result in resource problems because there is
no corresponding cleanup.
You are strongly advised to not allow this automatic behaviour, by
calling \fIcurl_global_init(3)\fP yourself properly.
See the description in \fBlibcurl\fP(3) of global environment
requirements for details of how to use this function.
.SH RETURN VALUE
If this function returns NULL, something went wrong and you cannot use the
other curl functions.

View File

@ -11,13 +11,22 @@ curl_global_cleanup - global libcurl cleanup
.BI "void curl_global_cleanup(void);"
.ad
.SH DESCRIPTION
curl_global_cleanup must be called once (no matter how many threads or libcurl
sessions that'll be used) by every application that uses libcurl, after all
uses of libcurl is complete.
This function releases resources acquired by \fBcurl_global_init\fP.
This is the opposite of \fIcurl_global_init(3)\fP.
You should call \fIcurl_global_cleanup()\fP once for each call you make
to \fIcurl_global_init\fP, after you are done using libcurl.
\fBThis function is not thread safe.\fP You must not call it when any
other thread in the program (i.e. a thread sharing the same memory) is
running. This doesn't just mean no other thread that is using
libcurl. Because \fBcurl_global_cleanup()\fP calls functions of other
libraries that are similarly thread unsafe, it could conflict with any
other thread that uses these other libraries.
See the description in \fBlibcurl\fP(3) of global environment
requirements for details of how to use this function.
Not calling this function may result in memory leaks.
.SH "SEE ALSO"
.BR curl_global_init "(3), "
.BR libcurl "(3), "

View File

@ -11,22 +11,31 @@ curl_global_init - Global libcurl initialisation
.BI "CURLcode curl_global_init(long " flags ");"
.ad
.SH DESCRIPTION
This function should only be called once (no matter how many threads or
libcurl sessions that'll be used) by every application that uses libcurl.
This function sets up the program environment that libcurl needs. Think
of it as an extension of the library loader.
If this function hasn't been invoked when \fIcurl_easy_init(3)\fP is called,
it will be done automatically by libcurl. It is adviced that you do not rely
on this automatic call, but instead call \fIcurl_global_init(3)\fP properly.
This function must be called at least once within a program (a program is
all the code that shares a memory space) before the program calls any other
function in libcurl. The environment it sets up is constant for the life
of the program and is the same for every program, so multiple calls have
the same effect as one call.
The flags option is a bit pattern that tells libcurl exact what features to
The flags option is a bit pattern that tells libcurl exactly what features to
init, as described below. Set the desired bits by ORing the values together.
In normal operation, you must specify CURL_GLOBAL_ALL. Don't use any other
value unless you are familiar with and mean to control internal operations
of libcurl.
You must however \fBalways\fP use the \fIcurl_global_cleanup(3)\fP function,
as that cannot be called automatically for you by libcurl.
\fBThis function is not thread safe.\fP You must not call it when any
other thread in the program (i.e. a thread sharing the same memory) is
running. This doesn't just mean no other thread that is using
libcurl. Because \fIcurl_global_init()\fP calls functions of other
libraries that are similarly thread unsafe, it could conflict with any
other thread that uses these other libraries.
See the description in \fBlibcurl\fP(3) of global environment
requirements for details of how to use this function.
Calling this function more than once will cause unpredictable results. If that
is not enough, calling this function from more than one thread may also cause
unpredictable results.
.SH FLAGS
.TP 5
.B CURL_GLOBAL_ALL
@ -47,3 +56,4 @@ other curl functions.
.BR curl_global_init_mem "(3), "
.BR curl_global_cleanup "(3), "
.BR curl_easy_init "(3) "
.BR libcurl "(3) "

View File

@ -13,10 +13,11 @@ in-depth understanding on how to program with libcurl.
There are more than a twenty custom bindings available that bring libcurl
access to your favourite language. Look elsewhere for documentation on those.
All applications that use libcurl should call \fIcurl_global_init(3)\fP
exactly once before any libcurl function can be used. After all usage of
libcurl is complete, it \fBmust\fP call \fIcurl_global_cleanup(3)\fP. In
between those two calls, you can use libcurl as described below.
libcurl has a global constant environment that you must set up and
maintain while using libcurl. This essentially means you call
\fIcurl_global_init(3)\fP at the start of your program and
\fIcurl_global_cleanup(3)\fP at the end. See GLOBAL CONSTANTS below
for details.
To transfer files, you always set up an "easy handle" using
\fIcurl_easy_init(3)\fP, but when you want the file(s) transferred you have
@ -86,6 +87,10 @@ Never ever call curl-functions simultaneously using the same handle from
several threads. libcurl is thread-safe and can be used in any number of
threads, but you must use separate curl handles if you want to use libcurl in
more than one thread simultaneously.
The global environment functions are not thread-safe. See GLOBAL CONSTANTS
below for details.
.SH "PERSISTENT CONNECTIONS"
Persistent connections means that libcurl can re-use the same connection for
several transfers, if the conditions are right.
@ -103,3 +108,96 @@ libcurl will be closed and forgotten.
Note that the options set with \fIcurl_easy_setopt(3)\fP will be used in on
every repeated \fIcurl_easy_perform(3)\fP call.
.SH "GLOBAL CONSTANTS"
There are a variety of constants that libcurl uses, mainly through its
internal use of other libraries, which are too complicated for the
library loader to set up. Therefore, a program must call a library
function after the program is loaded and running to finish setting up
the library code. For example, when libcurl is built for SSL
capability via the GNU TLS library, there is an elaborate tree inside
that library that describes the SSL protocol.
\fIcurl_global_init()\fP is the function that you must call. This may
allocate resources (e.g. the memory for the GNU TLS tree mentioned
above), so the companion function \fIcurl_global_cleanup()\fP releases
them.
The basic rule for constructing a program that uses libcurl is this:
Call \fIcurl_global_init()\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()\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 isn't actually required that the functions be called at the beginning
and end of the program -- that's 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
isn't 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 can't
generally know what these libraries are, or whether other threads are
using them.
The global constant situation merits special consideration when the
code you are writing to use libcurl is not the main program, but rather
a modular piece of a program, e.g. another library. As a module,
your code doesn't know about other parts of the program -- it doesn't
know whether they use libcurl or not. And its code doesn't necessarily
run at the start and end of the whole program.
A module like this must have global constant functions of its own,
just like \fIcurl_global_init()\fP and \fIcurl_global_cleanup()\fP.
The module thus has control at the beginning and end of the program
and has a place to call the libcurl functions. Note that if multiple
modules in the program use libcurl, they all will separately call the
libcurl functions, and that's OK because only the first
\fIcurl_global_init()\fP and the last \fIcurl_global_cleanup()\fP in a
program changes anything. (libcurl uses a reference count in static
memory).
In a C++ module, it is common to deal with the global constant
situation by defining a special class that represents the global
constant environment of the module. A program always has exactly one
object of the class, in static storage. That way, the program
automatically calls the constructor of the object as the program
starts up and the destructor as it terminates. As the author of this
libcurl-using module, you can make the constructor call
\fIcurl_global_init()\fP and the destructor call
\fIcurl_global_cleanup()\fP and satisfy libcurl's requirements without
your user having to think about it.
\fIcurl_global_init()\fP has an argument that tells what particular
parts of the global constant environment to set up. In order to
successfully use any value except \fICURL_GLOBAL_ALL\fP (which says to
set up the whole thing), you must have specific knowledge of internal
workings of libcurl and all other parts of the program of which it is
part.
A special part of the global constant environment is the identity of
the memory allocator. \fIcurl_global_init()\fP selects the system
default memory allocator, but you can use \fIcurl_global_init_mem()\fP
to supply one of your own. However, there is no way to use
\fIcurl_global_init_mem()\fP in a modular program -- all modules in
the program that might use libcurl would have to agree on one
allocator.
There is a failsafe in libcurl that makes it usable in simple
situations without you having to worry about the global constant
environment at all: \fIcurl_easy_init()\fP sets up the environment
itself if it hasn't been done yet. The resources it acquires to do so
get released by the operating system automatically when the program
exits.
This failsafe feature exists mainly for backward compatibility because
there was a time when the global functions didn't exist. Because it
is sufficient only in the simplest of programs, it is not recommended
for any program to rely on it.

View File

@ -190,7 +190,7 @@ curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
*/
CURLcode curl_global_init(long flags)
{
if (initialized)
if (initialized++)
return CURLE_OK;
/* Setup the default memory functions here (again) */
@ -217,7 +217,6 @@ CURLcode curl_global_init(long flags)
idna_init();
#endif
initialized = 1;
init_flags = flags;
return CURLE_OK;
@ -263,6 +262,9 @@ void curl_global_cleanup(void)
if (!initialized)
return;
if (--initialized)
return;
Curl_global_host_cache_dtor();
if (init_flags & CURL_GLOBAL_SSL)
@ -275,7 +277,6 @@ void curl_global_cleanup(void)
amiga_cleanup();
#endif
initialized = 0;
init_flags = 0;
}