From: Emil Dotchevski on
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
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
>> 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
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
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