From: Emil Dotchevski on
I want to terminate a process with an exit code, and I want that exit
code to be returned by the process being killed. Note that I can't
synchronize with the process and I can't "wait a little" before I kill
it.

On my system (XP SP3) the test below fails nearly 100% of the time.
When it fails, the process being killed returns zero (instead of 42.)

Any ideas?

#include <string>
#include <sstream>
#include <iostream>
#include <assert.h>
#include <windows.h>

void check_call( bool result, char const * call, char const * file,
int line );
#define CHECK_CALL(call) check_call(call,#call,__FILE__,__LINE__);

int
main( int argc, char const * argv[] )
{
if( argc>1 )
{
assert( !strcmp(argv[1],"inf") );
for(;;)
{
}
}
int errors=0, zeroes=0;
for( int i=0; i!=100; ++i )
{
STARTUPINFO sinfo;
ZeroMemory(&sinfo,sizeof(STARTUPINFO));
sinfo.cb=sizeof(STARTUPINFO);
PROCESS_INFORMATION pe;
char cmd_line[32768];
strcat(strcpy(cmd_line,argv[0])," inf");
CHECK_CALL((CreateProcess(0,cmd_line,0,0,TRUE,
0,0,0,&sinfo,&pe)!=0));
CHECK_CALL((CloseHandle(pe.hThread)!=0));
CHECK_CALL((TerminateProcess(pe.hProcess,42)!=0));
CHECK_CALL((WaitForSingleObject(pe.hProcess,INFINITE)
==WAIT_OBJECT_0));
DWORD ec=0xFFFFFFFF;
CHECK_CALL((GetExitCodeProcess(pe.hProcess,&ec)!=0));
assert(ec!=0xFFFFFFFF);
CHECK_CALL((CloseHandle(pe.hProcess)!=0));
errors += (ec!=42);
zeroes += (ec==0);
}
std::cout << errors << ',' << zeroes << std::endl;
return 0;
}

std::string
get_last_error_str( DWORD err )
{
std::ostringstream s;
s << err;
LPVOID lpMsgBuf=0;
if( FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|
FORMAT_MESSAGE_IGNORE_INSERTS,
0, err, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (LPSTR)
&lpMsgBuf, 0, 0) )
{
assert(lpMsgBuf!=0);
std::string msg;
try
{
std::string((LPCSTR)lpMsgBuf).swap(msg);
}
catch(
... )
{
}
LocalFree(lpMsgBuf);
if( !msg.empty() && msg[msg.size()-1]=='\n' )
msg.resize(msg.size()-1);
if( !msg.empty() && msg[msg.size()-1]=='\r' )
msg.resize(msg.size()-1);
s << ", \"" << msg << '"';
}
return s.str();
}

void
check_call( bool result, char const * call, char const * file, int
line )
{
assert(call && *call);
assert(file && *file);
assert(line>0);
DWORD le=GetLastError();
if( !result )
{
std::cerr << file << '(' << line << "):\n" << call << " failed
\nand GetLastError returned:" <<
get_last_error_str(le) << std::endl;
exit(2);
}
else if( le )
{
std::cerr << file << '(' << line << "):\n" << call << "
succeeded,\nbut GetLastError returned" <<
get_last_error_str(le) << std::endl;
exit(3);
}
}

--
Emil Dotchevski
Reverge Studios, Inc.
http://www.revergestudios.com/reblog/index.php?n=ReCode
From: David Lowndes on
>On my system (XP SP3) the test below fails nearly 100% of the time.

So presumably, once in a blue moon it's OK?

>When it fails, the process being killed returns zero (instead of 42.)
>
>Any ideas?

What happens if you wait a short time after starting the process
before terminating it?

Dave
From: Nobody on
"Emil Dotchevski" <emildotchevski(a)gmail.com> wrote in message
news:95e9d35d-60e0-414d-81bb-cef3c12d485b(a)k2g2000pro.googlegroups.com...
>I want to terminate a process with an exit code, and I want that exit
> code to be returned by the process being killed. Note that I can't
> synchronize with the process and I can't "wait a little" before I kill
> it.
>
> On my system (XP SP3) the test below fails nearly 100% of the time.
> When it fails, the process being killed returns zero (instead of 42.)

Is the call to TerminateProcess successful?


From: Emil Dotchevski on
On Feb 3, 4:40 pm, David Lowndes <Dav...(a)example.invalid> wrote:
> >On my system (XP SP3) the test below fails nearly 100% of the time.
> So presumably, once in a blue moon it's OK?

Right. I suspect it succeeds if the system randomly happens to do
something else that slows the TerminateProcess down. Like me hitting
Ctrl+F5 frantically. :)

> >When it fails, the process being killed returns zero (instead of 42.)
>
> 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; Sleep of about 5 ms makes it
work almost always on my computer. However, my real use case is such
that I can't afford to Sleep, and the process I'm killing is launched
by a 3rd party program.

By the way, I get feedback that the code I posted works on Win7.

Emil Dotchevski
Reverge Studios, Inc.
http://www.revergestudios.com/reblog/index.php?n=ReCode
From: Emil Dotchevski on
On Feb 3, 4:54 pm, "Nobody" <nob...(a)nobody.com> wrote:
> "Emil Dotchevski" <emildotchev...(a)gmail.com> wrote in message
>
> news:95e9d35d-60e0-414d-81bb-cef3c12d485b(a)k2g2000pro.googlegroups.com...
>
> >I want to terminate a process with an exit code, and I want that exit
> > code to be returned by the process being killed. Note that I can't
> > synchronize with the process and I can't "wait a little" before I kill
> > it.
>
> > On my system (XP SP3) the test below fails nearly 100% of the time.
> > When it fails, the process being killed returns zero (instead of 42.)
>
> Is the call to TerminateProcess successful?

Yes. All function calls succeed.

Emil Dotchevski
Reverge Studios, Inc.
http://www.revergestudios.com/reblog/index.php?n=ReCode