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

I need a perl script to fork another program (on linux) and wait for it to finish (it may take a minute), while monitoring for keyboard input (to allow the user to abort and kill the forked process)

The IPC modules I've looked at give very complicated examples when all I want to do is this:

system(command) until (done or user_aborted)
A real simple example would help. This is on Linux. Thanks!

Replies are listed 'Best First'.
Re: How to kill forked process
by Tanktalus (Canon) on Feb 17, 2005 at 04:11 UTC

    "All I want to do is ..."

    To be honest, that's not quite as easy as your pseudo-code implies.

    if (my $pid = fork()) { # parent monitor($pid); } elsif (defined $pid) { # child exec(@command); } else # fork failed. { # How do you want to handle this? }
    Of course, monitor is the tough part. You'll probably need to set a signal handler for SIGCHLD - so you'll know when the child exits. You'll want to probably use Term::ReadKey, although I'm not sure if ReadKey will return if interrupted with a signal. And then, if you do get the right key, you can use kill to kill the $pid we got from fork.

    I hope this helps, barring some more adventerous monk writing a more complete example.

      thanks for your reply, but I goofed in my problem description. See my reply to the next post.

      (why do I have to reply to a particular post, instead of the general thread?)

Re: How to kill forked process
by moot (Chaplain) on Feb 17, 2005 at 04:18 UTC
    The reason IPC examples are complicated is because IPC is complicated! Think about all the ways that either the parent or the child can end, and how each is to be notified of the other's death.

    That said, you might be able to get away with the following (mostly pseudo-) code:

    my $pid = fork(); if ($pid) { # in the parent wait for a keypress via your favourite method here if an abort occurs.. kill 15, $pid; # sigspec to taste exit; # parent is done # you'll probably want POSIX WNOHANG here, otherwise waitpid will bl +ock waitpid, $pid # child exited normally } elsif (defined $pid) { # in the child system("run_groovy_command"); exit; # tell daddy i'm done } else { die "Cannot fork: try spoon\n"; }
      I think I goofed in my problem description, I didn't know what fork() was, I thought it was a general term to spawn a completely different program, not duplicate itself.

      In fact the system() command might work for me if I am able to interrupt it. I just want to spawn a system process but be able to kill it upon an interrupt signal from the user.

      Sorry for my ignorance. And thanks for your reply.

        You can just use the control-c(SIG-INT) to interrupt the current system, and move to the next in the list. Try:
        #!/usr/bin/perl $rc = system('top'); $rc = system('date; sleep 10'); $rc = system('top'); $rc = system('date; sleep 10'); $rc = system('top');

        I'm not really a human, but I play one on earth. flash japh
Re: How to kill forked process
by TilRMan (Friar) on Feb 17, 2005 at 09:14 UTC
    Try system (perldoc -f system) and see if it does what you need.