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

Hi Monks,

I'm writing a script that functions a deamon to start and watch over other processes. That is, you can tell the daemon to start some other process (e.g. "ls -lh /var/www/html" or something) and it will fork it off as a child and tell you when it's done. The daemon stays running 24/7. You can also tell it to kill a process that it has started. The way I currently have things set up, the code looks something like this:
my $pid = fork(); if ($pid == 0) { #this is the child exec("$command_you_requested_me_to_start") or die "Couldn't start +!\n"; } elseif (!defined($pid)){ #some sort of error occured...say so and die print "ERROR!\n"; exit; }

Then when I try to kill a process that I've started, I use code something like this:
my $attempt = kill('INT', $pid_of_child_process);

Unfortunately when I do this, the child process I've tried to kill simply becomes a zombie process and don't go away until the daemon script exits. I tried using 'KILL' instead of 'INT' and also played briefly with 'CHLD' and 'SIG_IGN' but got the same results.

Can anyone show me a better way to start/kill these child processes? It would be best if I could use SIGINT for the killing part, since some of the processes will be catching SIGINT and exiting gracefully accordingly....

Replies are listed 'Best First'.
Re: Controlling Child Processes
by tcf22 (Priest) on Oct 23, 2003 at 18:14 UTC
    Perhaps something like this (taken from perlman:perlipc). There are more elaborate examples there also.
    sub REAPER { $waitedpid = wait; # loathe sysV: it makes us not only reinstate # the handler, but place it after the wait $SIG{CHLD} = \&REAPER; } $SIG{CHLD} = \&REAPER; ##Do something with fork

    - Tom

Re: Controlling Child Processes
by Anonymous Monk on Oct 23, 2003 at 17:28 UTC
Re: Controlling Child Processes
by zentara (Cardinal) on Oct 24, 2003 at 14:18 UTC
    Try this:
    #!/usr/bin/perl my $kidpid; if ( !defined( $kidpid = fork() ) ) { #fork returned undef, so failed die "Cannot fork: $!"; } elsif ( $kidpid == 0 ) { # fork returned 0, so this branch is child exec("xterm -e top"); # if exec fails, fall through to the next statement die "can't exec : $!"; } else { # fork returned 0 nor undef # so this branch is parent sleep(5); my $result = kill "TERM", $kidpid; print "Killed child process $kidpid (result $result)\n"; sleep(5); }