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

Hello Monks,

I have a wrapper script done in perl which runs the program (blastall) with backticks. I use backticks to make sure that any errors get passed ahead. However the program I'm running seems to ignore signal sent by wrapper script, when wrapper receives SIGTERM. So how can i know what pid my child program has, so that i can make a signal handler to send it a SIGKILL when my wrapper gets SIGTERM?

I tried to use: '$SIG{INT} = sub { die };', but this does not seem to work.

Update: typo fixing.

Replies are listed 'Best First'.
Re: How to get child pid from backtics
by zejames (Hermit) on Dec 09, 2004 at 14:12 UTC
    If you require that you parent script have full control over the 'blastall' child, I really advise you to use fork, for exemple :
    my $pid = fork; die unless defined $pid; if ($pid) { # Parent. Do whatever you want } else { # Child do 'blastall.pl'; }

    --
    zejames
      UPDATE: Ok, got it fixed. Shoud be $kid = waitpid(-1,0). I quite don't understand how it matches the correct PID, but this seems to be working.

      I'm having problems with the execution and fork. Probably as I have never used it before. So is this correct way to use it? Where does the waitpid go and how does it work? How the program flow go from here?
      #!/usr/bin/perl # # Wrapper takes is the arguments of the blastall binary # changes directory to binarys directory # adds binary name # runs it # Needs to be able to trap normal signals and definedly kill the proce +ss, # as it ignores some which it should not. # use warnings; use strict; use File::Basename; use sigtrap qw(handler catch_signal normal-signals); my $pid; # blastalls pid after fork sub catch_signal { print STDERR "SIGNAL:",shift," blast should be $pid\n"; kill (9,$pid); exit; } print "Going\n"; my $dir=dirname($0); chdir $dir; unshift (@ARGV,"./blastall"); $pid = fork; die "Can't fork: $!\n" unless defined $pid; if ($pid) { # Parent. Do whatever you want print "In parent.\n"; my $kid=0; do { waitpid ($pid,0); } until ($kid == -1); } else { # Child print "In child.\n"; exec (@ARGV) or die "Unable to exec: $!"; } print "After fork if.\n"; # this was used after `@ARGV` to get error message if executing failed # if ($?!=0) { # warn "@ARGV failed: ",$?,":",$?>>8,"\n"; # exit $?; # } print "Exiting.\n"; exit;
      I was kind of hoping that it would not involve fork :).

        In fact, you are anyway. Backticks does not avoid it, it only does hide it from you...


        --
        zejames
Re: How to get child pid from backtics
by fglock (Vicar) on Dec 09, 2004 at 14:17 UTC

    note: this pid is actually the pid of the subshell. (updated)

    $pid = open( my $proc, "-|", "ls -l" ); print "pid $pid\n"; my @lines = <$proc>; print @lines;
      No, it's not the pid of the subshell, because there isn't a subshell. Perl only calls a subshell if the command to call contains characters that are special to the shell (except whitespace) - otherwise Perl will split given string on whitespace, and execute the command (with any arguments) directly. In this case, perl will do an execv of ls, passing it -l as its sole argument.

      Had you written:

      $pid = open(my $proc, "-","ls -l>/tmp/foo");
      then $pid would contain the pid of a shell.