in reply to TSHARK Child: Windows open2 non-blocking read, or redesign?

When pipe-spawning children, I usually follow this pattern to clean up stray detached child processes:

my $CHILD = open2(\*READ, \*WRITE, "$TSHARK $TSHARKOPTS") || die "Can't open2 child process: $!"; push @children, $CHILD; END { kill 9 => @children; };

Of course, this simple approach is no good if you have a machine where PIDs get recycled very fast, or if you have a long running process with many children that have finished. Then a cleanup of @children if a child finishes is in order.

Replies are listed 'Best First'.
Re^2: TSHARK Child: Windows open2 non-blocking read, or redesign?
by afoken (Chancellor) on Oct 12, 2010 at 09:36 UTC

    I would collect the children's PIDs in a hash (as keys with meaningless values), remove them in a SIGCHLD handler from the hash, and kill() the remaining ones a litte bit more carefully (first SIGTERM, then SIGKILL). Of course, that won't work on Windows (no signals, no fork(), no exec(), no kill() in the API, just an incomplete emulation inside perl).

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

      kill works for processes outside of Perl as well on Win32.

        kill works for processes outside of Perl as well on Win32.

        ... for a very limited definition of "works". You can use kill to terminate other processes, but you can't send them signals, because Windows doesn't implement signals.

        Inside a perl.exe process that pseudo-fork()ed a child-pseudo-process, signals may work, but not outside that process.

        Simple example:

        killme.pl

        #!perl use strict; use warnings; $SIG{'HUP'}=sub { print "Got a HUP signal\n"; }; $SIG{'TERM'}=sub { print "Got a TERM signal\n"; }; open my $f,'>','pid.txt' or die "Could not write pid.txt: $!"; print $f "$$\n"; close $f; $|=1; print "Waiting to be killed\n"; while (1) { print '.'; sleep 30; }

        killer.pl:

        #!perl use warnings; use strict; open my $f,'<','pid.txt' or die "Start killme.pl first"; my $pid=<$f>; close $f; for my $sig (qw( HUP TERM KILL )) { print "Sending $sig ...\n"; kill($sig,$pid); sleep 2; }

        Open two terminals on a Linux system, start both scripts (killme.pl first), and you see this:

        tty1tty2
        /home/foken>perl killme.pl Waiting to be killed .Got a HUP signal .Got a TERM signal .Killed /home/foken>
        /home/foken>perl killer.pl Sending HUP ... Sending TERM ... Sending KILL ... /home/foken>

        Open two command shells on Windows, start both scripts (again killme.pl first) and you see this:

        Shell 1Shell 2
        F:\>perl killme.pl Waiting to be killed . F:\>
        F:\>perl killer.pl Sending HUP ... Sending TERM ... Sending KILL ... F:\>

        Note that sending HUP terminated killme.pl, completely ignoring the fact that it has set up a HUP signal handler.

        One could argue that Windows has no HUP signal, so let's remove the relevant code parts and watch again:

        Shell 1Shell 2
        F:\>perl killme.pl Waiting to be killed . F:\>
        F:\>perl killer.pl Sending TERM ... Sending KILL ... F:\>

        Ooops, death by SIGTERM, again ignoring the signal handler inside killme.pl.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)