views:

231

answers:

4

My Win32 console applicaton uses a third-party library. After it exits WinMain global objects destruction begins and an AV happens somewhere deep inside. I'm really tempted to just write

TerminateProcess( GetCurrentProcess(), 0 );

somewhere near the end of WinMain. If I do this the application ends gracefully.

But MSDN says that doing so can compromise the state of global data maintained by dynamic-link libraries (DLLs) which is not clear. I understand that if I have some global object its destructor is not run and I risk not finalizing a database connection or something similar. I don't have anything like that in my program.

What exactly is the risk when using TerminateProcess? How do I determine if I can use it for my purpose?

+5  A: 

Based on the documentation for that and ExtiProcess it seems the primary concern is that DLL's are unloaded without a call to DllMain with the flag DLL_PROCESS_DETACH.

My 2cents: The documentation is being paranoid that you will upset some critical operation which runs in DllMain + DLL_PROCESS_DETACH. Anyone who depends on that to maintain critical state is already at the mercy of task manager so I don't see a huge risk in using this API.

JaredPar
+1, but I would put it the other way round: using TerminateProcess() is just as dangerous as killing processes via Task Manager.
j_random_hacker
+4  A: 

It depends how you interpret "global data". If you take it to mean (as I normally would) data stored in the process's address space, then the advice makes no sense - we know that memory is going to disappear, so who cares what happens to that?

So it may be referring to OS-wide stuff that a DLL may have done, that persists outside the lifetime of any process. A simple example would be a temporary file that might need to be cleaned up; crash the process too many times and you'll run out of disk space, so probably best not to make a habit of it.

Daniel Earwicker
+3  A: 

AFAIK, if you're not doing anything "fancy" (which includes but is not limited to: creating threads, locks, DB connections, using COM objects), nothing terrible will happen. But as Earwicker says, you don't know what OS-wide stuff a DLL is doing, and you certainly don't know if that will change in the future, so relying on this is very fragile.

Aren't you curious to know why this access violation is occurring? It may well be the sign of something that became corrupted much earlier on. Please at least confirm that the bug is caused by this 3rd-party library, e.g. by writing a program that links with the library but whose main() does nothing, and confirming that this causes the same crash.

j_random_hacker
Good idea with empty main()
Anton Tykhyy
+2  A: 

Generally the bad things will happen when interacting with objects outside of your process. For an example say you have some shared memory used by multiple processes that your process will write to and other processes read and or write to. Typically to synchronize the reading and writing a mutex is used. If a thread in your process has acquired the mutex and is in the middle of making changes when TerminatePorcess is called, the mutex will be abandoned and the shared memory potentially left in an inconsistent state.

I suspect you are miss using one of the third party libraries. DllMain is somewhat limiting so the library may have initialize and uninitialize functions that you are supposed to call.

Stephen Nutt
Selected for a nice example of a case that could cause problems. After debugging this very problem I found out the problem was that the library wasn't always calling our callback function that would perform proper deinitialization prior to unloading. Without deinitialization done static global objects were destroyed in the order which lead to first destroying a heap with an object pool and then trying to deallocate those objects. That caused the crash since object pointers were already pointing to deallocated heap memory.
sharptooth
Since there was a point in our code that was always called during application termination I just added a step equivalent to what was done by that callback. And the problem is gone.
sharptooth
Glad to hear you solved the problem
Stephen Nutt