[gnutls-dev] Re: living without global variables

Simon Josefsson jas at extundo.com
Wed Dec 28 10:13:52 CET 2005

bryanh at giraffe-data.com (Bryan Henderson) writes:

>>The variables are used by code that has to parse X.509 certificates or
>>other PKCS structures.
> Now I'm starting to wonder just how constant this information is (I'm
> talking about the information now, not the program variables that
> represent it).  We know it's constant for the life of a program, but
> is it constant for all programs?  I.e. could it conceivably be
> generated at library build time and loaded whole by the
> program/library loader?

Yes, that is roughly how it works now.  Read the code, the global
variables are another representation of the information in the
generated lib/gnutls_asn1_tab.c and lib/pkix_asn1_tab.c files.  It may
be possible to make those two files contain more complex data
structures that is easier to use directly by the ASN.1 library.  That
would avoid the allocation/deallocation of the intermediary format.

>>4) Store the global variables in thread-local storage.  There is a
>>   gnulib module that works with pthread, pth, solaris threads and
>>   win32 threads to do this.
> Thanks; I forgot that one.  I've only ever seen it in libc, probably
> because of the portability difficulty.

I think gettext uses it.  I don't like the portability problems, and
the problems of being in an application that uses two thread packages
at the same time.  So I don't think that is a good solution.

>>Here is another solution for removing the global variables without
>>changing any APIs [1]: replace all uses of the global variable with a
>>function call to a function that generate a local copy of the ASN.1
>>structures.  This will be slower, but would work.
> It _sounds_ impractically slow.  But then I don't know enough about the
> code to know.

Modularity comes with a price... if we can't come up with something
else, we at least know there is a solution.

>>Simply have all libraries using GnuTLS call gnutls_global_init() in a
>>thread-unsafe initialization function, ultimately mutex synchronized
>>by the application.
> That initialization function (call it foo_global_init()) is more than
> thread-unsafe.  Thread-unsafe means you can't call foo_global_init()
> simultaneously from two threads.  But foo_global_init() not only can't
> be called while another thread is calling it, but also not while
> another thread is running at all.  Because that thread might be
> calling gnutls_global_init() via something other than
> foo_global_init().
> But I guess this is probably the way to go, considering how much
> easier it is to implement.  The paradigm is that the global
> initialization/termination must propagate through all the libraries up
> to the main program initialization code where the program is a single
> thread.  The object oriented libraries are a little less object
> oriented, since you can't just haul off and create an object whenever
> you want (you have to think about the global state), but it's a whole
> lot less coding.  And I guess the program can't dynamically load any
> of these libraries.
> I note that even removing global variables from GnuTLS and libgcrypt
> just begins to solve my problem, because libcurl also uses 4 other
> libraries, in various environments, that have the same global
> initialization requirement.  But the single-threaded reference-counted
> global init thing can work for all of them.

And I think that is a reasonable approach, unless we can think of a
better solution.  Many complex libraries I've seen have a global setup
function, e.g., gettext, glib.

When we have a replacement for libgcrypt, we can reconsider this
issue, and then I think it would even be possible to get a thread safe
gnutls_global_init() -- the only remaining problem then would be the
two global variables.  And that might be fixed by generating the
*_asn1_tab.c files in a different format, that the asn1 library can
read without having to allocate and set up a linked list for it.

>>[1] Changing APIs is really bad, that is why I'm having trouble with
>>your proposed approach.
> I thought I cleared this up before, but here it is again, so I guess
> not.  Is it your opinion that changing an API by adding optional
> functions to it is really bad?  That's what I proposed.  In contrast,
> the "really bad" change to an API most people mean is doing something
> that makes programs that use the existing API have to change.

Changing APIs are bad, adding APIs are fine.  I simply could not see
how you would fix the problem with your approach without changing the
API, that's why I repeated it.


More information about the Gnutls-devel mailing list