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

Perl 5.8 Redhat Linux I need a forked function that more or less is an infinite heartbeat to unconditionaly terminate if parent dies. If parent is hard killed (-9) child does not terminate, Code example below.
#!/usr/bin/perl #heart beat funtion, infinite sub beat() { print "IM THE CHILD\n"; while(1) { print "Beat $i\n"; sleep 2; } exit(0); } #put heartbeat in background so whatever app is doing doesnt effect th +is. my $cpid = fork(); if ($cpid == 0) { &beat(); } ## parent stuff here ..... print "IM THE PARENT\n"; sleep 10; print "Bye\n"; #I can kill the child directly but if parent is killed child still run +s. Need child to exit when parent exits. kill TERM, $cpid; exit(0);

Replies are listed 'Best First'.
Re: Deamon: Need Child to exit if parent dies
by JavaFan (Canon) on Jan 04, 2010 at 22:42 UTC
    Swap the role of the parent and child (that is, let the parent do the heartbeating). Assuming you're using Unix (perhaps other OSses do the same, but I don't know them well enough), if a child process terminates, the parent receives a SIGCHLD. Then add to the parent:
    $SIG{CHLD} = sub {exit};
    Otherwise, you may be able to use a pipe between the parent and the child. The child should receive a SIGPIPE if it tries to read from the pipe after the parent died. But I haven't tried that in code.
Re: Deamon: Need Child to exit if parent dies
by MidLifeXis (Monsignor) on Jan 04, 2010 at 22:38 UTC

    SIGKILL (9) cannot be trapped by a process - the OS just stops scheduling the process. You will need to have the child monitor the parent process to see if it still exists (perhaps with kill 0, ... (see kill), and take action based on that.

    See also documentation for $PID, specifically the information about getppid.

    --MidLifeXis

      Agreed. I would check to see if my parent ID changed to init (1). Then the child knows it became an orphan.
Re: Daemon: Need Child to exit if parent dies
by shmem (Chancellor) on Jan 04, 2010 at 23:00 UTC

    See kill and getppid. Here's a recipe:

    #!/usr/bin/perl print "process $$ started\n"; if ((my $pid = fork) == 0) { my $ppid = getppid; while (1) { sleep 1; unless (kill 0, $ppid) { print "child: parent($ppid) gone, exiting.\n"; exit; } else { print "child: parent($ppid) still alive...\n"; } } } else { my $secs = int rand 20; print "parent: sleeping $secs seconds\n"; sleep $secs; } print "parent: exiting after 1 second\n"; sleep 1;
      That may not work correctly. The parent may exit, and its PID reused before the child gets a change to check, or either process may have changed UID (which is not uncommon for daemons) - the kill 0 will then fail, but all kill 0 tells you is whether the current process can send a signal to the other one - not existence is only one reason why a signal cannot be send.