From: Emil Dotchevski on 5 Feb 2010 16:33 On Feb 5, 11:43 am, Jonathan de Boyne Pollard <J.deBoynePollard- newsgro...(a)NTLWorld.COM> wrote: > I was hoping that someone would tell me why my program isn't working. > > Someone did. M. "m" hit the nail exactly on the head. You're simply so determined to cling on toyour chocolate-covered bananathat you're not even listening. M. "m" hit the nail on the head with respect to the chocolate-covered banana, too. I do appreciate a "why don't you try this instead" attitude, but I still want to know if my code is doing something wrong. I don't want to abandon a viable (according to the documentation, AFAICS) approach that might be failing due to bugs in my code. Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode
From: Hector Santos on 5 Feb 2010 22:48 Emil Dotchevski wrote: > On Feb 5, 11:43 am, Jonathan de Boyne Pollard <J.deBoynePollard- > newsgro...(a)NTLWorld.COM> wrote: >> I was hoping that someone would tell me why my program isn't working. >> >> Someone did. M. "m" hit the nail exactly on the head. You're simply so determined to cling on toyour chocolate-covered bananathat you're not even listening. M. "m" hit the nail on the head with respect to the chocolate-covered banana, too. > > I do appreciate a "why don't you try this instead" attitude, but I > still want to know if my code is doing something wrong. I don't want > to abandon a viable (according to the documentation, AFAICS) approach > that might be failing due to bugs in my code. Emil, if you are looking for software walkthru based on the code posted there are a number of "annal" things people can waste time here with you, but overall I think you wanted to have "perfect" control of spawning and termination and returning the exit codes. Overall you basically have: CreateProcess(0,cmd_line,0,0,TRUE,0,0,0,&sinfo,&pe); CloseHandle(pe.hThread); TerminateProcess(pe.hProcess,42); WaitForSingleObject(pe.hProcess,INFINITE); GetExitCodeProcess(pe.hProcess,&ec); In my view, what you are presuming that TerminateProcess() will always be correct, regardless if the child process was successfully loaded and started. The question then needs to be ask if CreateProcess will only return when the child process has indeed started. The answer to that is what MSDN says this: When a parent process creates a child process, the CreateProcess() function returns without waiting for the child process to finish its initialization. In short, there would be timing "unknowns here" and the reason it appears to work more often when you add a sleep() before the TerminateProcess() is because you now add context switching and thus provided more time for the other threads to complete its initialization. You might want to consider a "YIELD" or "POKE" concept which is equivalent to a Sleep(0) before the TerminateProcess() This will also provide a context switch that will also provide the increased illusion that it works more often. But overall, you can't depend on "time" to synchronize this. You need to have ome sort of synchronization object that allows you to wait on. Since you indicated you have no control over the child process (3rd party) thus can't rely on using a named kernel object, you should explore WaitForInputIdle(). However, in my products experience where we also had needs to spawn 3rd party software with force terminate parent controls, WaitForInputIdle() was not always reliable because the child process might not be waiting for user input. Maybe doing both a Sleep(0) and WaitForInputIdle() together is sufficient for you needs? I did some test myself, using XP SP3. Original Code: Iterations 100 I can't repeat issue 1000 Intermittently repeat issue, like every other run With Adding Sleep(0), I can not repeat issue at 1000 but at 3000 iterations I was able to repeat it. Unless you can get something out of the child process to sync on, you won't get a perfect timing here. I am scratching my head as to why you need such micro timing precision between child process initialization completion and force termination in a practical world? -- HLS
From: David Lowndes on 6 Feb 2010 04:55 >> What happens if you wait a short time after starting the process >> before terminating it? > >The more Sleep I add before calling TerminateProcess, the more likely >it is for the program to work correctly; OK, so how about using WaitForInputIdle instead of sleeping? Dave
From: Emil Dotchevski on 6 Feb 2010 14:02 Hector, thanks for trying the code. On Feb 5, 7:48 pm, Hector Santos <sant9...(a)nospam.gmail.com> wrote: > In my view, what you are presuming that TerminateProcess() will always > be correct, regardless if the child process was successfully loaded > and started. ....or return an error. > When a parent process creates a child process, the > CreateProcess() function returns without waiting for the > child process to finish its initialization. TerminateProcess does not require that the process being terminated has finished its initialization, so this can't be the problem I'm experiencing. Also, the process I'm terminating does terminate. This page: http://msdn.microsoft.com/en-us/library/ms686722%28VS.85%29.aspx states that: The exit code for a process is either the value specified in the call to ExitProcess or TerminateProcess, or the value returned by the main or WinMain function of the process. If a process is terminated due to a fatal exception, the exit code is the value of the exception that caused the termination. In this particular case, the process being terminated is an infinite loop. It does not return from main() and does not call ExitProcess (I would be OK if I don't get the exit code I'm passing to TerminateProcess, if the process being terminated managed to exit or was in the process of exiting.) It would seem that my program shows that there might be another, undocumented place the exit code could come from. > I did some test myself, using XP SP3. > > Iterations > 100 I can't repeat issue You mean it worked? What did it print? (it prints the number of failures, so zero would indicate that it worked.) Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode
From: Hector Santos on 6 Feb 2010 17:14
Emil Dotchevski wrote: > Hector, thanks for trying the code. > > On Feb 5, 7:48 pm, Hector Santos <sant9...(a)nospam.gmail.com> wrote: >> In my view, what you are presuming that TerminateProcess() will always >> be correct, regardless if the child process was successfully loaded >> and started. > > ...or return an error. > >> When a parent process creates a child process, the >> CreateProcess() function returns without waiting for the >> child process to finish its initialization. > > TerminateProcess does not require that the process being terminated > has finished its initialization, so this can't be the problem I'm > experiencing. Also, the process I'm terminating does terminate. > > This page: http://msdn.microsoft.com/en-us/library/ms686722%28VS.85%29.aspx > states that: > > The exit code for a process is either the value specified in > the call to ExitProcess or TerminateProcess, or the value > returned by the main or WinMain function of the process. > If a process is terminated due to a fatal exception, the > exit code is the value of the exception that caused the > termination. > > In this particular case, the process being terminated is an infinite > loop. It does not return from main() and does not call ExitProcess (I > would be OK if I don't get the exit code I'm passing to > TerminateProcess, if the process being terminated managed to exit or > was in the process of exiting.) > > It would seem that my program shows that there might be another, > undocumented place the exit code could come from. > >> I did some test myself, using XP SP3. >> >> Iterations >> 100 I can't repeat issue > > You mean it worked? What did it print? (it prints the number of > failures, so zero would indicate that it worked.) Righ (it worked). But its an illusion. I ran it a few more times with 100 and it didn't provided the expected result at least one time in the loop. Now do this, start a run and quickly grab you mouse and shake it around to cause mouse events in the system. Watch out the errors count climb and slow down as the mouse becomes still. Emil, Windows is not a RTOS (Real Time OS) where you can make predictable timing sequences and thread residence times. Here, we don't know where and when TerminateProcess() is killing the child process. It may not have reached the main block infinite loop. It might have never even reached the main entry point at all and was is still initializing other stuff, or it was blocked due to other context switching, etc. You simply have no control of where TerminateProcess() will kill the process. You are the mercy of the system context switching forced or natural. Now. personally, I wonder if there is a "difference" in behavior with TerminateProcess() in various OSes because to me, the exit code you provide SHOULD always be the process exit code regardless if where the initialization the child is at. So in that vain, I might agree there is a valid issue/bug here to consider. That might explain why it works all the time in VISTA/W7, because it fixed some process information issue with terminated processes. Or maybe there is so much extra overhead in VISTA/W7 that it too provides the greater illusion that it was fixed. So if we want to ask the question; Should TerminateProcess() always return the exit code you provide? that might be a valid question, and if NOT, what are the reasonable explanations when it will not in a TRUE result condition Now, consider this statement: "Do not terminate a process unless its threads are in known states. If a thread is waiting on a kernel object, it will not be terminated until the wait has completed. This can cause the application to hang." Could that mean that unless the child reaches the main (thread) entry point, that TerminateProcess() exit code MAY NOT be reliable? I think it should be in ALL cases, apparently not in some OSes. However, I think its clear that it depends on where the child process is during its startup and initialization - at least under XP that I tried it under. Finally, TerminateProcess() is something that is use under last change conditions with the underlining engineering expectation that pulling the rug from under the feet of something is not graceful and results should not always be considered reliable. But you do know one thing: You Terminated the Process, you KNOW that the exit code is regardless of what anything else said. It is 42 PERIOD! Who cares what the "System" says it is. It has to be 42 and nothing else. What we could be questioning is why didn't this 42 propagate thru the system so that the PUSH and the POP came out as you expected? I agree, that would make me ask think about it, because it theory GetExitCodeProcess() should return what your set with TerminateProcess(). Put from a practical standpoint, for me,its not something I would need. For us 3rd party software is expected to have an input queue and I/O as well. Maybe MS did address this in Vista/W7, or again, all its extra overhead adds natural delays making it appear that it its perfectly aligned. -- HLS |