If you want to "whack" the shell and all of its subprocesses, place the shell into its own process group. That way, when it forks off other processes, they will be in the same group, and you can send a signal to all of them in one fell swoop by killing zero minus the process group's ID. (You might want to check out the perlipc man page for more on this stuff.)

Here's some code that shows how to do it. First, we need a troublemaker program to test out our mighty kung-fu on. Here's a shell script that spawns five subprocesses that all emit annoying output. We'll love telling this guy to "kick the oxygen habit" later.

#!/bin/bash # File: forkage.sh for f in $(seq 1 5); do ( while : ; do echo $f; sleep 1; done ) & done wait
And now the Perl code that runs the troublemaker, reads output from it (and its spawn), and after 20 lines kills 'em all off to rescue us from the annoying brood:
#!/usr/bin/perl use warnings; use strict; $SIG{CHLD} = 'IGNORE'; # to make sure there are no zombies sub run_shell(@) { my $pid = open my $pipe, "-|"; die "can't open forked pipe': $!" unless defined $pid; if ($pid) { # parent return { pid => $pid, pipe => $pipe }; } # child open STDERR, ">&STDOUT" or die "can't dup 2>&1: $!"; setpgrp; # move into its own process group exec @_; # give control of child to command die "exec @_ failed: $!"; # should never get here } my $subshell = run_shell qw(./forkage.sh); my $output_from_subshell = $subshell->{pipe}; my $lines_left = 20; print while defined($_ = <$output_from_subshell>) and $lines_left--; kill "HUP", -$subshell->{pid};
The run_shell function is where most of the magic happens. It serves as a wrapper around open that gives us more control over the resulting child process. It forks off a child process that has its STDOUT wired to $pipe, which the parent can read from later. The child then starts a new process group with the same ID as its own pid via setpgrp and finally uses exec to run the command we passed in as arguments.

Meanwhile, the parent returns from the call to run_shell with a hash containing the pid of and pipe from the child. The parent grabs the pipe's filehandle and reads 20 lines from it, printing each one in passing. Then, getting sick of all the chatter, it sends a hang-up signal to every process in the child's process group, thus shutting their annoying behavior down.

Hope this helps.


In reply to Re: Killing all processes launched using open() by tmoertel
in thread Killing all processes launched using open() by SmilingBuddha

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.