Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Killing a Win32 process, a return value ?

by abachus (Monk)
on Mar 03, 2007 at 01:43 UTC ( #603005=perlquestion: print w/replies, xml ) Need Help??

abachus has asked for the wisdom of the Perl Monks concerning the following question:

Hello all,

I sure I must have missed something here, the penny just hasn't yet dropped and thus request the help of the wise. You see i'm trying to write some code to kill processes on a Win32 machine. I've started to bend my head around the documentation at hand (Win32::Process).

Win32::Process::KillProcess($pid, $exitcode) Terminates any process identified by $pid. $exitcode will be set to the exit code of the process.

Now I have had success with this yes, i can kill processes ok and i can visually see that, but my program doesn't know that because it doesn't know what the return value means (neither do I).

If i do :

my rval=Win32::Process::KillProcess($pid,$exitcode);

$rval seems to equal '1' upon success or an arbitrarily large number on failure. I've got this all wrong haven't I. Can you help ? I'd have assumed the call would return the PID on success or undef on failure, no ?

many thanks for your time,

Isaac Close.
  • Comment on Killing a Win32 process, a return value ?

Replies are listed 'Best First'.
Re: Killing a Win32 process, a return value ?
by BrowserUk (Patriarch) on Mar 03, 2007 at 03:53 UTC

    Basically, you found a bug in the implementation:

    BOOL KillProcess(pid, exitcode) DWORD pid unsigned int exitcode CODE: { HANDLE ph = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); if (ph) { RETVAL = TerminateProcess(ph, exitcode); if (RETVAL) CloseHandle(ph); } } OUTPUT: RETVAL

    Or maybe several bugs.

    1. If your perl process is not running with sufficient priviledges to open the target process PROCESS_ALL_ACCESS, then RETVAL is never being (visibly) set and you are getting whatever value it is initialised to by XSUBPP (if any, the docs are less than clear about this), or some random value in the ram it inherits.
    2. If OpenProcess() succeeds, then you get the return value of TerminateProcess(), which is non-zero for success, or zero for failure in which case calling GetLastError() should tell you why it failed.

    It's possible that when it fails, the arbitrarily large number you are getting is the OS failure code. It would be worth comparing it against the numeric realisation of $^E.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Killing a Win32 process, a return value ?
by thezip (Vicar) on Mar 03, 2007 at 02:48 UTC
    I looked at the docs for Win32::Process, and saw that $exitcode was the only thing that was being set. I didn't see anything about a return (l)value...

    Maybe you should perform your test on $exitcode instead?

    Where do you want *them* to go today?

      The documentation is inaccurate and the code is buggy. From http://search.cpan.org/src/JDB/libwin32-0.26/Process/Process.xs:

      BOOL KillProcess(pid, exitcode) DWORD pid unsigned int exitcode CODE: { HANDLE ph = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); if (ph) { RETVAL = TerminateProcess(ph, exitcode); if (RETVAL) CloseHandle(ph); } } OUTPUT: RETVAL

      So, RETVAL isn't initialized so if OpenProcess() fails, RETVAL will be random garbage from the stack (some "large number", as observed, or sometimes 0 or 1, unfortunately, I guess -- unless the "arbitrary" observation is inaccurate and it is actually a standard Win32 marker value like 0xCCCCCCCC). If OpenProcess() succeeds, then RETVAL will say whether or not TerminateProcess() was successful or not.

      And exitcode is not an output parameter so it isn't set to anything. It specifies what exit code the terminated process will use (as documented in the Win32 SDK).

      Luckily, both OpenProcess() and TerminateProcess() call SetLastError() (Win32 SDK again) so you can check $^E to see if they failed (if you do it fast enough). For example:

      $^E= 0; Win32::Process::KillProcess( $pid, 1 ); my $err= $^E; die "Failed to kill process, $pid: $err\n" if $err;

      But someone should really fix the docs and code for this module, especially since it leaks a process handle if TerminateProcess() fails.

      - tye        

        Indeed.

        Where do you want *them* to go today?
        Thanks for the output everyone gave in this thread, all has been considered ;) I have chosen to go with the code suggested by Tye with regards to testing the condition of $^E.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://603005]
Approved by kyle
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (4)
As of 2022-08-15 13:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?