Holy cow, I wrote a book!
A customer reported that their program would very sporadically
crash in the function
The customer was kind enough to provide a stack trace at the point
of the crash:
The customer wondered,
"Could the problem be that my cleanup group does not have
MSDN seems to suggest that this is okay."
The exception being thrown is
but that doesn't really say much.
But that's okay, because the smoking gun isn't the exception
It's in the stack.
Do you see it?
The code is calling
from inside DllMain
while handling the
Looking further up the stack, you can see this was triggered by
a call to ExitProcess,
and now all the stuff you know about
how processes exit
For example, that the first thing that happens is that all threads
are forcibly terminated.
That's your next clue.
Observe that the customer's DLL is trying to communicate with the
thread pool during process termination.
But wait, all the threads have already been terminated.
It's trying to communicate with a nonexistent thread pool.
The thread pool realizes,
"Hey, like I've already been destroyed.
I can't do what you ask because there is no thread pool any more.
You want me to block until all currently executing callback
but those callback functions will never finish (if they even exist at all)
because the threads hosting their thread pool got destroyed.
Not that I can tell whether they are executing or not,
because I am already destroyed.
The only options are to hang or crash.
I think I'll crash."
The customer needs to restructure the program so that it either
cleans up its thread pool work before the
or it can simply skip all thread pool operations when the reason for
the DLL_PROCESS_DETACH is process termination.