January 07, 2019
https://issues.dlang.org/show_bug.cgi?id=19556

          Issue ID: 19556
           Summary: main thread static ctor/dtor should run both shared
                    and thread-local simultaneously
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P1
         Component: druntime
          Assignee: nobody@puremagic.com
          Reporter: schveiguy@yahoo.com
                CC: code@dawg.eu

A classic chicken and egg problem. Let's say each thread establishes a Logger object:

Logger tlsLogger;

static this()
{
   tlsLogger = new Logger(Thread.getThis);
}

Now, we have a problem that in shared static constructors, tlsLogger is uninitialized, so:

import logger;
shared static this()
{
   tlsLogger.logInfo("initializing module doodad"); // segfault
}

But really, this is a problem with how shared constructors and destructors are run -- the main thread is instantiated by the OS, and so we really should run those thread static ctors first. But those static ctors may be written to depend on the shared static ctors!

There is an easy solution, which requires no changes to the language or compiler. Instead of running module shared static constructors *as a whole group* in the main thread, and then running the thread local static constructors *as a whole group*, run both per module in the right order, only for the main thread. Subsequent threads can just run the thread local ctors/dtors. Cleanup has to be performed in the same way as well.

This puts the dependency in the right place -- the module depends on its imported modules, no matter how the static data is initialized. And it continues to allow the thread local constructors to rely on the shared data being initialized.

Thanks to Dru for the idea: https://forum.dlang.org/post/zefxmyvloqsbmhmaqwfe@forum.dlang.org

--