module initialization order issue

Steven Schveighoffer schveiguy at yahoo.com
Mon Mar 4 08:02:15 PST 2013


On Sun, 03 Mar 2013 07:01:11 -0500, Benjamin Thaut  
<code at benjamin-thaut.de> wrote:

> When modules are initialized, druntime will first run the module  
> initializers before running the module tls initializers ignoring the  
> dependencies between the modules. This will lead to a access of a  
> unitialized module if the module ctor of one module uses tls data of  
> another module. Example:
>
> module a:
>
> class TLSStuff
> {
>    public int i;
> }
>
> TLSStuff g_tlsStuff;
>
> static this()
> {
>    g_tlsStuff = new TLSStuff();
> }
>
> module b:
> import a;
>
> shared static this()
> {
>    g_tlsStuff.i++; //null pointer access
> }
>
> Is this a bug, or is this intended beahvior? I always believed that with  
> all the dependency detenction that is done such situation should not  
> happen.

As has been discussed, this is intended behavior.

But I will go a bit further.  It is reasonable to assume that each thread  
being allocated will be assured that the shared data has already been  
initialized.  This makes logical sense as the shared data is initialized  
once, thread data is initialized whenever you start a new one.

So if we had the shared data depending on the first thread local data  
being initialized, you couldn't have ANY thread local data depending on  
the shared data being initialized.  I don't think this is the right  
decision.

But how can we solve this problem?  One possibility, while a bit awkward,  
is to identify when you are initializing the first thread.  Then use that  
knowledge to your advantage:

__gshared bool inFirstThread = true;

static this()
{
    if(inFirstThread) // shared constructor already has initialized tls  
stuff for us
       inFirstThread = false;
    else
       g_tlsStuff = new TLSStuff();
}

shared static this()
{
    // initialize main thread's tls stuff
    g_tlsStuff = new TLSStuff();
    g_tlsStuff.i++;
}

If you needed this idiom elsewhere, you could set the inFirstThread to  
false as the first statement in main.  Druntime could conceivably do  
something like this for you, if you are so inclined, file an enhancement.

-Steve


More information about the Digitalmars-d mailing list