Missing zombie at some point
I might have found a bug in a case that is maybe a corner case.
I am investigating a problem in our tests where a unit test launches an arbitrary executable (i used ping.exe, but works with other exe), waits for it to complete and then calls a function that ensures that we are not able to get a handle on this process again (i.e. we ensure there is no zombie, hence the name of the function :) WaitUntilProcessAndItsZombieAreDead). Everything worked fine with that but we changed something in the way we call the unittest and it broke, i.e. a zombie now remains... That's it for context.
So debugging all that, I discovered your tool. Previously I used RAMMap to detect zombies.
Here is the problem I got: Please note: I have a debugger attached to my unit test executable, in case it changes something. My code does that:
- Calls CreateProcess to launch ping,exe
- Waits for the process to be signaled: BOOST_REQUIRE( WaitForSingleObject( pi.hProcess, INFINITE ) == WAIT_OBJECT_0 );
- Closes the handles on the thread and process: BOOST_REQUIRE( CloseHandle( pi.hThread ) != 0 ); BOOST_REQUIRE( CloseHandle( pi.hProcess ) != 0 ); After closing the process handle, we do not see ping.exe in the zombie processes in ObjExp.exe, which seems reasonable to me, but RAMMap, after a refresh, still shows the process, as a zombie (0K private memory)...
- Then we call OpenProcess using the pid of ping.exe and we successfully get a handle on it, which would indicate that the process was still existing somewhere, as a zombie.
- At this moment, if I refresh ObjExp.exe, the zombie reappears from the... dead? :)
I don't know why, but it seems the process was hiding somewhere ObjExp.exe does not find it. Maybe linked to the debugger? If I get time, I could try it without the debugger if it can help.
I know, maybe what I try to do with WaitUntilProcessAndItsZombieAreDead is not that useful but that's another question ;)
Well, ObjExp is not perfect here :) The way it works is by finding handles to processes that are dead. However, even if there are zero handles, the object may still exist as a zombie if there is a kernel reference (rare, but possible). Once you opened ping for the second time, a handle was created, so ObjExp was able to find it and see it points to a dead process.
Ok, thanks for the explanation! I forgot to consider kernel references. So, corner case here. Could explain some strange situations that I witnessed in the past. Could maybe also explain the issue we are tracking in our code. We observe that if stdout is piped, the zombie stays alive and if it is not piped, it dies as we would expect.