in reply to forking, waiting, and killing child pids
Your usage of "&" in the command is not only unnecessary (the fork already runs "in the background"), it also is the primary reason your code doesn't work. Otherwise, your approach to create a new process group is perfectly fine, in case you need or want to kill an entire tree of child processes.
Compare the following (I replaced tcpdump with a simple sleep, which is irrelevant to the discussion):
#!/usr/bin/perl -w use strict; sub ps { system "ps Tf -o pid,ppid,pgrp,sid,cmd"; } $SIG{CHLD} = 'IGNORE'; my $snoop = fork(); if ( $snoop == 0 ){ setpgrp; system("sleep 20 &"); exit; } ps(); sleep 1; print "PID: $snoop\n"; printf "PGRP: %d\n", getpgrp($snoop); kill -1, getpgrp($snoop); ps(); __END__ PID PPID PGRP SID CMD 2360 2358 2360 2360 bash -rcfile .bashrc 19529 2360 19529 2360 \_ /usr/bin/perl -w ./964597.pl 19531 19529 19529 2360 \_ ps Tf -o pid,ppid,pgrp,sid,cmd 19533 1 19530 2360 sleep 20 PID: 19530 PGRP: -1 PID PPID PGRP SID CMD 2360 2358 2360 2360 bash -rcfile .bashrc 19529 2360 19529 2360 \_ /usr/bin/perl -w ./964597.pl 19534 19529 19529 2360 \_ ps Tf -o pid,ppid,pgrp,sid,cmd 19533 1 19530 2360 sleep 20
#!/usr/bin/perl -w use strict; sub ps { system "ps Tf -o pid,ppid,pgrp,sid,cmd"; } $SIG{CHLD} = 'IGNORE'; my $snoop = fork(); if ( $snoop == 0 ){ setpgrp; system("sleep 20 ;"); exit; } ps(); sleep 1; print "PID: $snoop\n"; printf "PGRP: %d\n", getpgrp($snoop); kill -1, getpgrp($snoop); ps(); __END__ PID PPID PGRP SID CMD 2360 2358 2360 2360 bash -rcfile .bashrc 19537 2360 19537 2360 \_ /usr/bin/perl -w ./964597.pl 19538 19537 19538 2360 \_ /usr/bin/perl -w ./964597.pl 19540 19538 19538 2360 | \_ sh -c sleep 20 ; 19541 19540 19538 2360 | \_ sleep 20 19539 19537 19537 2360 \_ ps Tf -o pid,ppid,pgrp,sid,cmd PID: 19538 PGRP: 19538 PID PPID PGRP SID CMD 2360 2358 2360 2360 bash -rcfile .bashrc 19537 2360 19537 2360 \_ /usr/bin/perl -w ./964597.pl 19542 19537 19537 2360 \_ ps Tf -o pid,ppid,pgrp,sid,cmd
As you can see in the first example, the child process (sleep) dissociates, i.e. the original process (your $snoop PID) is no longer alive, so getpgrp($snoop) fails, and you effectively kill nothing...
In the second example, however, without using "&"1, things work as intended. I.e., you have created a new process group (19538 here), which you are then killing successfully.
That said, unless you actually are running multiple child processes, there is no need to use the process group technique. As long as you can make sure that tcpdump is the only and immediate child process (for example using exec, as noted by halfcountplus (but without your "&" !)), killing that process directly would work without a problem.
BTW, to check whether a process is running, you can send it the "0" pseudo signal, e.g.
printf "child%s alive\n", kill(0, $snoop) ? "":" not";
___
1note that I'm using a ";" here in place of the "&", because the example is also meant to show that using an extra process group to kill multiple processes in one go, is working just fine. Without a shell meta character in the command (the semicolon in this case), Perl would optimize away the extra shell, so there would only be a single child process, which kind of defeats the purpose of using a process group...
|
---|
Replies are listed 'Best First'. | |
---|---|
Re^2: forking, waiting, and killing child pids
by sinmissing (Initiate) on Apr 20, 2012 at 15:47 UTC |