in reply to Re^6: Signal to parent-process. Does it affect it's children?
in thread Signal to parent-process. Does it affect it's children?

I've re-produced a small example that hopefully gives you an idea of the problem. Copy past below and you are able to see it from my perspective. The point is that everytime you run "kill -s USR1 <pid>" you will see that processes gets killed.

Put this content in "mainprogram" and 'chmod a+x'

#!/usr/bin/perl -w use strict; use warnings; use IPC::Open3; use IO::Select; my($StartedProcess); $SIG{USR1} = \&status; sub status () { $SIG{USR1} = \&status; print STDERR "Currently running: $StartedProcess\n"; } # Opens external program, and as long as it exists, checks # if there is data in the pipe (STDOUT/STDERR) sub createProcess () { my($line, $selector, @ready, $fh); $StartedProcess = open3(*CMD_IN, *CMD_OUT, *CMD_ERR, "./external.pp" +); close(CMD_IN); $selector = IO::Select->new(); $selector->add(*CMD_ERR, *CMD_OUT); while(@ready = $selector->can_read) { # do some operations on STDOUT/STDERR here } close(CMD_OUT); close(CMD_ERR); } my($pid) = fork; if($pid) { print "\t Created PID: $pid. run 'kill -s USR1 $pid'\n"; exit(0); } foreach(qw/1 2 3 4 5 6 7 8 9 10/) { createProcess(); } print STDERR "\n COMPLETED !"; exit(0);

Put this content in "external.pp" and 'chmod a+x'
#!/usr/bin/perl -w use strict; my $i = 0; while ($i <= 10) { sleep(3); $i+= 3; }

Replies are listed 'Best First'.
Re^8: Signal to parent-process. Does it affect it's children?
by shmem (Chancellor) on Sep 11, 2008 at 15:41 UTC

    The problem is that select() isn't re-entrant: it gets interrupted by the signal handler and doesn't resume, so you end up with an empty @ready array. That means you fall out of the while (@ready) {} loop; the sub returns, createProcess() is called again, the file handles are re-opened: the previous command is terminated.

    To work around that, add a flag variable which gets reset in the handler:
    my $redo; # flag sub status () { $SIG{USR1} = \&status; print STDERR "Currently running: $StartedProcess\n"; $redo = 1; # re-set flag } # Opens external program, and as long as it exists, checks # if there is data in the pipe (STDOUT/STDERR) sub createProcess () { my($line, $selector, @ready, $fh); $StartedProcess = open3(*CMD_IN, *CMD_OUT, *CMD_ERR, "./external.pp" +); close(CMD_IN); $selector = IO::Select->new(); $selector->add(*CMD_ERR, *CMD_OUT); $redo = 1; # set flag while($redo) { $redo = 0; # clear flag while(@ready = $selector->can_read) { # do some operations on STDOUT/STDERR here } warn "after inner loop\n"; } warn "closing CMD_OUT and CMD_ERR\n"; close(CMD_OUT); close(CMD_ERR); }

    Also, you should set up a SIGCHLD handler which clears the $selector after the child is gone.

      Thank you very much shmem (and everyone else)! The problem is no longer a problem.
      Apparantly it all boiled down to select() not being re-entrant.
      THANKS!