develooper Front page | perl.perl5.porters | Postings from April 2007

RE: [PATCH] Fix kill(0, $pid) on Windows

Thread Previous | Thread Next
From:
Jan Dubois
Date:
April 19, 2007 10:04
Subject:
RE: [PATCH] Fix kill(0, $pid) on Windows
Message ID:
019601c782a4$bb819e70$3284db50$@com
On Thu, 19 Apr 2007, Steve Hay wrote:
> Jan Dubois wrote:
> I get the same result as you using your test program, but I still have
> two problems or misunderstandings.

Sorry about that, my explanations have been somewhat incomplete.

Note that Perl really only supports 3 different signals on Windows when
you send them to an external process and not a forked pseudo-process:
SIGINT, SIGBREAK and SIGKILL.  SIGTERM is mapped to SIGBREAK, and I
think everything else is mapped to SIGKILL.

SIGKILL is implemented by calling TerminateProcess().

  http://msdn2.microsoft.com/en-us/library/ms686714.aspx

SIGINT and SIGBREAK are sent using GenerateConsoleControlEvent().

  http://msdn2.microsoft.com/en-us/library/ms683155.aspx

This later function is restricted to signaling processes in the same
console as the caller.

win32/win32.c(mykill) implements the kill(-$sig, $pid) functionality
internally by walking the parent/child relations in the process tree.
It does not know about process groups.  It does not implement the
$pid==0 case specifically.

Therefore kill($sig,0) will not do anything for signals except SIGINT
and SIGBREAK (and signals mapped to them, like SIGTERM).
GenerateConsoleCtrlEvent() itself implements the $pid==0 case by
sending the signal to all processes running in the same console as
the caller.

> Firstly, what I was trying (and which still doesn't work) is to start a
> perl.exe in one command prompt and note its PID, e.g.
> 
>  >perl -le "print $$; sleep 60"
> 2508
> 
> and then try to kill it using a perl.exe in another command prompt:
> 
> perl -e "kill 15, 2508"
> 
> I expected that to kill the first perl.exe (PID 2508), but it doesn't.
> Trying to kill the cmd.exe parent of PID 2508 instead (like your program
> does) also doesn't work.

It doesn't work because it is running in a different console.  You need
to start the process with system(1, ...) or Win32::Process to be able
to send it SIGINT or SIGBREAK signals.  Note that SIGINT doesn't work
either unless the child process re-enables Ctrl-C processing because
Perl uses CREATE_NEW_CONSOLE_GROUP in the CreateProcess() call.

> Of course, your program is different in that the perl.exe (and its
> parent cmd.exe) being killed is a child of the perl.exe that is trying
> to kill it, whereas I'm playing with two separate process trees. Is this
> expected behaviour?

It is not the parent/child relationship, but the fact that they are running
in the same console.  I did not expect this limitation, but I do understand
it now.
 
> Secondly, if I change the "kill 15, $pid" in your program to "kill 15,
> undef" instead then I was expecting the whole process tree to be killed,
> including the perl.exe that is issuing the kill(), as per your comment
> quoted at the very top of this email.
> 
> However, I still find that only the cmd.exe and its child perl.exe get
> killed, and the top-level perl.exe that issued the kill() hangs around
> for another 5 seconds until it says "done" and exits. This doesn't seem
> to be what you suggested would happen, unless I've misunderstood you.

This behavior is implemented by GenerateConsoleCtrlEvent().  I would have
expected that it would also generate the event in the calling process,
but it looks like it doesn't.

I'm still at a loss about what we should be doing about all this.  Should
we document the whole situation (in perlport, with a link from perlfunc?).
Or should we undo the kill(-$sig, $pid) functionality and move it into
Win32::Process:killtree() instead?

I have not been able to find any documentation on how we could determine
the processes belonging to a console-specific process group.

Starting with Windows XP there is GetConsoleProcessList().

  http://msdn2.microsoft.com/en-us/library/ms683170.aspx

I haven't tried it, but from the documentation it looks like it will provide
a list of all processes attached to the current console.  It doesn't give
us a list of processes inside our own console process group.  We could
use this function to implement kill(9, 0) to work on the same set of
processes as kill(15, 0).  I guess this might be useful sometimes, but
muddies the situation even further.

Cheers,
-Jan


Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About