rapide has asked for the wisdom of the Perl Monks concerning the following question:

I have a process that will run in the background like a daemon. I want that daemon to give me it's status whenever I send a specific signal to it.
My code for doing so is as follows:

my($Percent) = 50;
$SIG{HUP} = \&status;

sub status () {
print "\n I'm $Percent done.";
}

And I initiate it by sending: kill -s HUP <PID> or in perl: (kill "HUP", <PID>)
However, Although this works, It will kill my process if it's run two times within a short intervall. This is the error I get:

*** sysread(out): Interrupted system call

Q: Why does my process terminate after sending signals two times?
Q: Which signal is the best to use for something like printing status-info?
Q: Is it possible to make a new signal like "SIGSTATUS" ?
  • Comment on How to create private signals? (or block interruption)

Replies are listed 'Best First'.
Re: How to create private signals? (or block interruption)
by shmem (Chancellor) on Sep 01, 2008 at 20:00 UTC
    Q: Why does my process terminate after sending signals two times?

    Most likely you have SysV signals. Re-install the signal handler:

    sub status () { print "\n I'm $Percent done."; $SIG{HUP} = \&status; }
    Q: Which signal is the best to use for something like printing status-info?

    Anything trappable; from within, I'd use ALRM; from outside, SIGINT, SIGUSR1 or SIGUSR2.

    Q: Is it possible to make a new signal like "SIGSTATUS" ?

    No, since signals are routed through the kernel: it has a list you can't change.

Re: How to create private signals? (or block interruption)
by jwkrahn (Abbot) on Sep 01, 2008 at 19:35 UTC

    See: Signals.   And for user defined signals you can use SIGUSR1 and SIGUSR2.


      Thank you for your answer.
      Unfortunately I did not find any help on that page. It's written that
      Not all platforms automatically reinstall their (native) signal handlers after a signal delivery. This means that the handler works only the first time the signal is sent. The solution to this problem is to use POSIX signal handlers if available, their behaviour is well-defined.

      But the attached example did not work any better. Same problem and error :/

Re: How to create private signals? (or block interruption)
by psini (Deacon) on Sep 01, 2008 at 20:01 UTC

    The problem you are facing is many system routines are not reentrant, so they don't like being interrupted by another call to the same routine.

    In general it is better avoid commands that require system call in a signal handler: when possible use the handler to set up a flag to be used in your program main loop.

    Rule One: "Do not act incautiously when confronting a little bald wrinkly smiling man."

Re: How to create private signals? (or block interruption)
by cdarke (Prior) on Sep 02, 2008 at 07:56 UTC
      I'm using perl v5.8.5
      Use the Config module to find out whether you have reliable signals:
      use Config;
      print "Hurrah!\n" if $Config{d_sigaction};

      RESULT: Hurrah!

      To determine whether your interrupted system calls will automatically restart, look at your system's C signal.h include file: % egrep 'SAV_(RESTART|INTERRUPT)' /usr/include/*/signal.h

      RESULT:
      /usr/include/asm/signal.h: * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
      /usr/include/asm/signal.h: * SA_RESTART flag to get restarting signals (which were the default long ago)
      /usr/include/asm/signal.h:#define SA_RESTART 0x10000000
      /usr/include/asm/signal.h:#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */

      Basically I do not know what to do. I've tried those examples that you gave me link to, but it still gives me the warning. However, when I used $SIG{INT} = 'IGNORE'; I managed to delay the interruption with 2 seconds.

      UPDATE: I found out that if I'm running a single process/thread it works. It seems like the reasoning from crashing comes from the fact that I fork another process in the background. Do I have to put some handlers inside this fork aswell? Or is there any signal for "children" that I can use ?

        SIGCHLD is the signal the parent gets from the kernel when the child terminates. Other than that, there are no special "children signals."

        A forked child is an exact copy of the parent, until the child starts developing own ideas. Signal handlers should be the same in the child - if they are set up before forking, that is.

        I guess at this point I need to see a bit more of the code involved to make an educated guess.