[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.
Thanks,
Simon
More information about the Gnutls-dev
mailing list