in reply to Signal to parent-process. Does it affect it's children?

I've made all this work, but every time I send a signal to it to get the current status it kills the current process

Well, not for the code below on my box. I've added/changed some bits.

use IPC::Open3; my $status; sub status () { print "Status is: $status\n"; $SIG{USR1} = \&status; } $SIG{USR1} = \&status; print "$$\n"; my @paths; my $c = 10; push @paths,"sleep ".$c++ for 0 .. 3; $c = 0; foreach $path (@paths) { print "loop ",++$c,"\n"; my $pid = open3(*CMD_IN, *CMD_OUT, *CMD_ERR, $path); $status = $path; waitpid($pid, 0); print "after waitpid\n"; }

Running it and killing the process several times yields

3297 loop 1 Status is: sleep 10 Status is: sleep 10 Status is: sleep 10 after waitpid loop 2 Status is: sleep 11 Status is: sleep 11 Status is: sleep 11

so yes, waitpid is re-entrant (at least on my box) and sending USR1 doesn't advance the loop and re-open CMD_* (which would kill the child process implicitly). Did you notice the line

print "Status is: $status\n";

above? Do you have unbuffered I/O on STDOUT?

update: yes, some signals get propagated to the children (USR1 isn't among them). Adding these bits to the script

sub default { print "got SIG ".shift()."\n"} $SIG{$_} = \&default for keys %SIG; $SIG{USR1} = \&status;

and invoking a perl script

#!/usr/bin/perl # have to print to a terminal directly, # since default file handles are re-directed open O ,'>', '/dev/pts/1'; sub default { my $sig = shift; print O "child Status: got SIG$sig\n"; $SIG{$sig} = \&default; } $SIG{$_} = \&default for keys %SIG; sleep $_ for 1..shift;

yields, killing the main script with <Ctrl>-C:

3437 loop 1 child Status: got SIGINT got SIG INT got SIG CHLD after waitpid loop 2 ...

You might want to wrap your call to open3() into a subroutine which resets $SIG{USR1} to 'IGNORE' using local. I suspect your problem being elsewhere. BTW, on which platform do you run?

Replies are listed 'Best First'.
Re^2: Signal to parent-process. Does it affect it's children?
by rapide (Beadle) on Sep 07, 2008 at 21:47 UTC
    Hmmmm. I might be confused with functions being re-entrant and un-buffered I/O.

    What happens in my process is that I'm not having any waitpid but instead polling to check if a new line has been printed on the stream.
    Let me put the exact code since this might be something specific:

    $selector = IO::Select->new(); $selector->add(*CMD_ERR, *CMD_OUT); while(@ready = $selector->can_read) { foreach my $fh (@ready) { if(fileno($fh) == fileno(CMD_ERR)) { my $line = scalar <CMD_ERR>; print $line; } } }

    Basically if what your meaning by unbuffered is having lines on the stream which is not printed when the signal occur, then yes I very likely have.

    UPDATE: I've tried this on two systems. Opensolaris and SLC4, both 32 bit. My perl version is: v5.8.4

      Hi, maybe this is a stupid question but, how do you send the kill signal? E.g. kill -10 1234 sends the SIGUSR1 signal to process 1234 while kill -10 -1234 sends the signal to the whole process group (process 1234 plus its child processes). Just a thought...
        Good comment!

        I use kill -s HUP <pid> from the shell.
        I've also tried to do this from a unaffected script with:
         kill "USR1", <pid>
        So unless there are something I don't see here, Its not the problem :/