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

Update: Because you said here, that you send a HUP, not a USR1.

Sending a HUP to a process that isn't prepared to catch a SIGHUP will terminate. Exactly what you described and a lot of the helpful people here couldn't reproduce with USR1.

You might like to add an additional HUP handler $SIG{HUP} = \&status; to print the status on HUP reception. But I would not recommend this, since HUP is a signal that will be send from the OS e.g. when the system is shut down or an interactive connection is closed. Using USR1 or USR2 is the usual way to do it.

So the right way to get the status information would be kill -s USR1 <pid> (where <pid> is a positive integer). You could add a line like print "Status info: kill -s USR1 $$\n" to your program to get the correct PID without having to look for it.

If that doesn't work, I do not have much more ideas... yet.

Replies are listed 'Best First'.
Re^7: Signal to parent-process. Does it affect it's children?
by rapide (Beadle) on Sep 11, 2008 at 13:00 UTC
    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; }

      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!