From June to now, most of my time on this project was spent writing "The Rise of Microsoft". Researching and writing that thing took an inordinate amount of time. Also, I took a break to work primarily on another unreleased project I have before switching back to this one. I am proud of what I got here though and I feel like it is all coming together. My plans for the whitepapers are already well drafted and I know they will make an impact. I have learned a ton from working on this project and it has definitely given me something to idly think about and work on in my spare time. Finishing "The Problem with How Windows Uses Threads" was something I thought I wanted done before this release, but oh well. The main README is at about 50K words now, plus all the other smaller documents and you are looking at about a small novel's worth of technical writing. And technical writing takes multiple times longer than typical story writing. Anyway, this project is exciting for me - people who I show it to also really like it - and I am even more excited about what is to come!
Library Initializer Thread Join Experiment
Spawning a thread and waiting for its creation then exit from a module initializer or finalizer (the latter being the module subsystem lifetime).
This experiment deadlocks on the ntdll!LdrpInitCompleteEvent event object in the LdrpInitialize function during process startup. During process run-time the deadlock will occur a bit later on the ntdll!LdrpLoadCompleteEvent event object in the LdrpInitializeThread ➜ LdrpDrainWorkQueue function (due to running DLL_THREAD_ATTACH). If it was possible to still continue then thread creation or exit would further block when acquiring the ntdll!LdrpLoaderLock lock in the LdrpInitializeThread function also due to running DLL_THREAD_ATTACH routines at thread startup or DLL_THREAD_DETACH routines at thread exit.
The loader intertwining with the threading implementation as we see here represents an overextension of the loader because those components should have zero knowledge of each other much less share synchronization. In other words, these subsystems are tightly coupled.
Specifying the THREAD_CREATE_FLAGS_SKIP_LOADER_INIT (new in Windows 10) on NtCreateThreadEx can bypass these thread creation and exit blockers. However, I have not seen an occurrence of the Windows API internally spawning a thread with this flag, so these deadlocks remain prevalent.
The funny thing about these deadlocks is that since Ctrl + C on Windows works by spwaning a thread into a process, they hang your entire terminal indefinitely (you need to whip out Task Manager). It can also lock out some Windows debugging tools that work by remotely spawning a thread to break-in a process or ascertain some information about it.