Global initialization is not thread-safe (especially in DLLs) in Silver

My apologies. You’re right. I looked at the external check and assumed it was all. Now that I looked inside I see the spinlock protecting the initialization.

However experimenting with DllMain the way you suggested on my other post I noticed that if I have DllEntry function, the initialization happens in it, even if the function does not refer to the global (see example below), at least in debug builds.

This should be at least documented since this means that if there’s a user-defined DLL entry point, global initialization would happen with the loader lock held, which puts considerable restrictions on what is allowed to bone. (Or changed so that the initialization doesn’t happen in this function.)

The code is a simple variations on the example I put in my recent posts:

import rtl

struct SomeStruct {
    var s: String
    init() {
        s = "Hello, World!"
    }
}

var aStruct = SomeStruct()
var i : uint32_t

@SymbolName("__elements_dll_entry")
static func DllEntry() {
    i = 5
}

@DllExport
@CallingConvention(CallingConvention.Stdcall)
@SymbolName("_Foo")
func fgdgdf() -> Bool {
    MessageBox(nil, "A Message", "Foo", 0)
    MessageBox(nil, aStruct.s.FirstChar, "Foo", 0)
    return true
}

The constructor is called at this point:

0:000> k
 # ChildEBP RetAddr  
00 004ff26c 5bb8b43b SilverDLL1!SilverDLL1.SomeStruct::. [\__windows_drive__c\users\conio\documents\visual studio 2015\projects\silverdll1\silverdll1\program.swift @ 5] 
01 004ff27c 5bb8b3da SilverDLL1!SilverDLL1.<Global>::.cctor+0x1b [\__windows_drive__c\users\conio\documents\visual studio 2015\projects\silverdll1\silverdll1\program.swift @ 10] 
02 004ff2a0 5bb8b4c1 SilverDLL1!SilverDLL1.<Global>::get_aStruct+0x7a
03 004ff2a8 5bbb651b SilverDLL1!SilverDLL1.<Global>::DllEntry+0x11 [\__windows_drive__c\users\conio\documents\visual studio 2015\projects\silverdll1\silverdll1\program.swift @ 15] 
04 004ff2b4 771be746 SilverDLL1!RemObjects.Elements.System.ExternalCalls::DllMainCRTStartup+0x2b [\__windows_drive__c\ci\b\elements\937\source\islandrtl\source\windowshelpers.pas @ 1122] 
05 004ff2d4 7718cbef ntdll!LdrxCallInitRoutine+0x16
06 004ff320 77187baa ntdll!LdrpCallInitRoutine+0x7f
07 004ff3a0 77187a44 ntdll!LdrpInitializeNode+0x10e
08 004ff3c4 771a014d ntdll!LdrpInitializeGraphRecurse+0x5d
09 004ff3e0 77189012 ntdll!LdrpPrepareModuleForExecution+0x8f
0a 004ff428 7719b63e ntdll!LdrpLoadDllInternal+0x128
0b 004ff574 7719e8de ntdll!LdrpLoadDll+0xa2
0c 004ff5f8 753eda74 ntdll!LdrLoadDll+0x7e
0d 004ff63c 753eb881 KERNELBASE!LoadLibraryExW+0x144
0e 004ff650 0130172b KERNELBASE!LoadLibraryW+0x11
0f 004ff740 01301e8e SilverLoader1!main+0x2b [c:\users\conio\documents\visual studio 2015\projects\silverloader1\silverloader1\silverloader1.cpp @ 20] 
10 004ff754 01301cf0 SilverLoader1!invoke_main+0x1e [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 64] 
11 004ff7ac 01301b8d SilverLoader1!__scrt_common_main_seh+0x150 [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 253] 
12 004ff7b4 01301ea8 SilverLoader1!__scrt_common_main+0xd [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl @ 296] 
13 004ff7bc 76ca8654 SilverLoader1!mainCRTStartup+0x8 [f:\dd\vctools\crt\vcstartup\src\startup\exe_main.cpp @ 17] 
14 004ff7d0 771b4a77 KERNEL32!BaseThreadInitThunk+0x24
15 004ff818 771b4a47 ntdll!__RtlUserThreadStart+0x2f
16 004ff828 00000000 ntdll!_RtlUserThreadStart+0x1b

By the way I noticed another problem I’m pretty sure is valid :slight_smile: - Even if I change Generate Debug Symbols to True, I don’t get a PDB when building in Release mode. That’s why I couldn’t verify this happens in Release too. :slight_smile:

And since we’re at it, one more question - I noticed that when building a DLL I get a small .fx file produced along with the DLL (and the PDB, when in Debug). This doesn’t happen for Exe and WinExe projects. Is there a reason for that? Do the .fx files have any function or use on Windows?