The case of the DLL that was not present in memory despite not being formally unloaded, part 1 - The Old New Thing
Skip to main content
Dev Blogs
AI
All .NET posts
.NET MAUI<br>ASP.NET Core<br>Blazor<br>Entity Framework
C++<br>C#<br>F#<br>TypeScript
NuGet<br>Servicing<br>.NET Blog in Chinese
Microsoft for Developers<br>Agent Framework<br>Develop from the cloud<br>Xcode<br>ISE Developer<br>TypeScript<br>PowerShell<br>Python<br>Java<br>Java Blog in Chinese<br>Go<br>Microsoft Edge Dev<br>Microsoft 365 Developer<br>Microsoft Entra Identity Developer<br>Microsoft Entra PowerShell
Visual Studio<br>Visual Studio Code<br>Aspire
All things Azure<br>Azure SDK<br>Azure VM Runtime Team<br>Microsoft Azure<br>Azure Cosmos DB<br>Azure DocumentDB<br>Azure Data Studio<br>Azure SQL<br>DevOps<br>DirectX<br>Microsoft Foundry<br>Power Platform
OData<br>Unified Data Model (IDEAs)
Windows Command Line<br>#ifdef Windows<br>Inside MSIX<br>MIDI and music<br>React Native<br>The Old New Thing<br>Windows Developer
Raymond Chen
The team responsible for shell32.dll received a bug saying that they were responsible for a large number of crashes in a particular third party program. Opening the crash dumps showed the clear signs of a stack overflow:
# Child-SP RetAddr Call Site<br>00 000000ba`92851098 00007ff9`fed521c1 ntdll!_chkstk+0x37<br>01 000000ba`928510b0 00007ff9`feea5ace ntdll!RtlDispatchException+0x2d1<br>02 000000ba`92851300 00007ff9`fed4e02d ntdll!KiUserExceptionDispatch+0x2e<br>03 000000ba`92852060 00007ff9`fed5222f ntdll!RtlLookupFunctionEntry+0x8d<br>04 000000ba`928520b0 00007ff9`feea5ace ntdll!RtlDispatchException+0x33f<br>05 000000ba`92852800 00007ff9`fed4e02d ntdll!KiUserExceptionDispatch+0x2e<br>06 000000ba`92853560 00007ff9`fed5222f ntdll!RtlLookupFunctionEntry+0x8d<br>07 000000ba`928535b0 00007ff9`feea5ace ntdll!RtlDispatchException+0x33f<br>08 000000ba`92853d00 00007ff9`fed4e02d ntdll!KiUserExceptionDispatch+0x2e<br>09 000000ba`92854a60 00007ff9`fed5222f ntdll!RtlLookupFunctionEntry+0x8d<br>0a 000000ba`92854ab0 00007ff9`feea5ace ntdll!RtlDispatchException+0x33f<br>0b 000000ba`92855200 00007ff9`fed51f29 ntdll!KiUserExceptionDispatch+0x2e<br>0c 000000ba`92855f70 00007ff9`feea5ace ntdll!RtlLookupFunctionEntry+0x8d<br>0d 000000ba`928561c0 00007ff9`fed4e02d ntdll!RtlDispatchException+0x33f<br>...
The highlighted block of stack frames (from RtlLookupFunctionEntry to KiUserExceptionDispatch) repeated for a very long time.
We are clearly in some sort of recursive exception handling death spiral. An exception occurred, and the kernel has decided that it is not something that kernel mode can handle,¹ so it reflected the exception back into user mode for further processing (KiUserExceptionDispatch). While trying to figure out which exception handler to call, (RtlLookupFunctionEntry), we took an exception, which restarted the exception loop.
Eventually, all of these recursive exceptions exhausted the stack, and we take a stack overflow exception that terminates the process.
The bug was assigned to shell32 because it looked like shell32 was the source of the original exception. If you walk all the way back to the bottom of the stack, you get something like this:
23f 000000ba`9294c620 00007ff9`fed5222f ntdll!RtlLookupFunctionEntry+0x8d<br>240 000000ba`9294c670 00007ff9`feea5ace ntdll!RtlDispatchException+0x33f<br>241 000000ba`9294cdc0 00007ff9`fed4e02d ntdll!KiUserExceptionDispatch+0x2e<br>242 000000ba`9294db20 00007ff9`fed5222f ntdll!RtlLookupFunctionEntry+0x8d<br>243 000000ba`9294db70 00007ff9`feea5ace ntdll!RtlDispatchException+0x33f<br>244 000000ba`9294e2c0 00007ff9`fcba0af0 ntdll!KiUserExceptionDispatch+0x2e<br>245 000000ba`9294f018 00007ff9`fde2ad13 combase!CoTaskMemFree<br>246 000000ba`9294f020 00007ff9`fc7abc75 shell32!wil::details::string_maker::~string_maker+0x13<br>247 000000ba`9294f050 00007ff9`fc7ab897 ucrtbase!::operator()+0xa5<br>248 000000ba`9294f0a0 00007ff9`fc7ab84d ucrtbase!__crt_seh_guarded_call::operator()+0x3b<br>249 000000ba`9294f0d0 00007ff9`fc7d2f0c ucrtbase!execute_onexit_table+0x3d<br>24a 000000ba`9294f110 00007ff9`fdff4645 ucrtbase!__crt_state_management::wrapped_invoke+0x2c<br>24b 000000ba`9294f140 00007ff9`fdff476e shell32!dllmain_crt_process_detach+0x45<br>24c 000000ba`9294f180 00007ff9`fee9f6fe shell32!dllmain_dispatch+0xe6<br>24d 000000ba`9294f1e0 00007ff9`fed4bcae ntdll!LdrpCallInitRoutineInternal+0x22<br>24e 000000ba`9294f210 00007ff9`fedcd37f ntdll!LdrpCallInitRoutine+0x10e<br>24f 000000ba`9294f280 00007ff9`fedcc54e ntdll!LdrShutdownProcess+0x17f<br>250 000000ba`9294f390 00007ff9`fdcb18ab ntdll!RtlExitUserProcess+0x9e<br>251 000000ba`9294f3c0 00007ff9`e754882e kernel32!ExitProcessImplementation+0xb<br>252 000000ba`9294f3f0 00007ff9`e754f344 mscoreei!RuntimeDesc::ShutdownAllActiveRuntimes+0x2fa<br>253 000000ba`9294f6d0 00007ff9`e66f464b mscoreei!CLRRuntimeHostInternalImpl::ShutdownAllRuntimesThenExit+0x14<br>254 000000ba`9294f700 00007ff9`e66f44c9 clr!EEPolicy::ExitProcessViaShim+0x8b<br>255 000000ba`9294f760 00007ff9`e66f441e clr!SafeExitProcess+0x9d<br>256 000000ba`9294f9e0 00007ff9`e66f3f44 clr!HandleExitProcessHelper+0x3e<br>257 000000ba`9294fa10 00007ff9`e66f3e24 clr!_CorExeMainInternal+0xf8<br>258...