Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Automatically killing a child

by Massyn (Hermit)
on May 19, 2006 at 02:01 UTC ( [id://550396]=perlquestion: print w/replies, xml ) Need Help??

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

#!/fellow/monks.pl On both AIX and Mandrake Linux, I'm experiencing a problem where programs spawned from within a perl script doesn't get killed when the parent dies. Yeah, children should live longer than their parents, but not in a perl script, I would think. Here's my code (and I've tried many different ways of opening tail)..

#!/usr/bin/perl open (HTML, "-|") or exec("tail","-f","testlog.txt"); print while <HTML>;
So touch testlog.txt, run the script, and start a 2nd session. Do a ps -ef and you'll see the process running, along with the spawned tail. Kill the parent, and the child becomes almost orphaned, using the inittab as it's parent. How can I kill the child when the parent dies, or at least spawn the child that it's dependant on the parent's survival??
[gmassyn@apt01m04 gmassyn]$ ps -ef |grep test gmassyn 7755 7712 0 21:57 pts/0 00:00:00 /usr/bin/perl ./testb. +pl gmassyn 7756 7755 0 21:57 pts/0 00:00:00 tail -f testlog.txt gmassyn 7758 7712 0 21:57 pts/0 00:00:00 grep test [gmassyn@apt01m04 gmassyn]$ kill -9 7755 [gmassyn@apt01m04 gmassyn]$ [1]+ Killed ./testb.pl [gmassyn@apt01m04 gmassyn]$ ps -ef |grep test gmassyn 7756 1 0 21:57 pts/0 00:00:00 tail -f testlog.txt gmassyn 7764 7712 0 21:57 pts/0 00:00:00 grep test [gmassyn@apt01m04 gmassyn]$

Thanks!

     |\/| _. _ _  ._
www. |  |(_|_>_>\/| | .net
                /
The more I learn the more I realise I don't know.
- Albert Einstein

Replies are listed 'Best First'.
Re: Automatically killing a child
by BrowserUk (Patriarch) on May 19, 2006 at 04:02 UTC

    See perlopentut for details, but note that piped-opens return the pid of the forked child.

    #!/usr/bin/perl my $kid = open (HTML, "-|") or exec("tail","-f","testlog.txt"); print while <HTML>; kill 2, $kid;

    You can use that to kill or wait or waitpid, but as tail -f file will never terminate* unless the file goes away, you will probably need to kill it.

    That said, if the file never goes away, tail will never terminate, so your print while <HTML> will never get eof, so you will never exit that loop in order to try and use kill.

    *those versions of tail I've used.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Automatically killing a child
by Zaxo (Archbishop) on May 19, 2006 at 04:32 UTC

    I'm surprised that the child doesn't terminate, since that is the action of the system default SIGHUP handler. If open or something else modifies that handler to keep the process running, this,

    local $SIG{HUP} = sub { exit 0 };
    should make sure the child terminates right after the parent does.

    After Compline,
    Zaxo

Re: Automatically killing a child
by mojotoad (Monsignor) on May 19, 2006 at 08:16 UTC
    You know, every now and then this happens. You're cruising along, monitoring your various ssh sessions, browsing the web in between bursts of programming, and you come across a subject line such as this.

    It's good, every now and then, to be emphatically reminded that we don't quite live in the real world.

    :)

    Matt

      I once, quite innocently, created a method (in another programming language) called KillAllDisabledChildren().

      When I went back to the code a couple of days later I thought "hmmm...." and changed it to something like RemoveAllHiddenSubwindows().

Re: Automatically killing a child
by ioannis (Abbot) on May 19, 2006 at 03:10 UTC
    For the two-argument open() , the '-|' argument means fork.

    The parent can reap the children with wait(), or waitpid(), or for some operating systems can reap them automatically by setting the CHLD signal. See perlipc for examples.

Re: Automatically killing a child
by sgifford (Prior) on May 19, 2006 at 03:44 UTC
    Children don't die automatically when their parent does. To kill them you'll have to, well, kill them: keep track of their PIDs, and kill them in an END block or $SIG{INT} handler.
Re: Automatically killing a child
by bbfu (Curate) on May 19, 2006 at 04:26 UTC
    If you have it, you can use pkill -g <GID> '.*' to kill the group of processes, I think.

    bbfu
    Black flowers blossom
    Fearless on my breath

Re: Automatically killing a child
by ikegami (Patriarch) on May 19, 2006 at 02:20 UTC

    I don't see any children. exec doesn't spawn children. exec executes a program in the current process. In other words, tail and the program that launches it are never running at the same time, because tail was launched via exec.

    In fact, it looks like you executed your script twice. Once as process 7755, and once as process 7756.

    Update: Nevermind. Apparently open -| returns the child pid. I don't see any mention of this in the docs. If open returned its usual status, exec would only get called when the pipe failed, and that's the scenerio I thought we had.

      If you open a pipe on the command '-' , i.e., either '|-' or '-|' with 2-arguments (or 1-argument) form of open(), then there is an implicit fork done, and the return value of open is the pid of the child within the parent process, and 0 within the child process.

      It's in there, just hidden way on down.

Re: Automatically killing a child
by roboticus (Chancellor) on May 19, 2006 at 13:05 UTC
    Massyn:

    I don't know what's going on, so this is pure speculation. But I think that tail is waiting until its input stream is closed. But with your script, tail's input stream is the terminal session's output stream (STDOUT). Thus, I think tail is waiting for your terminal session to close it's output stream before it exits.

    Again, this is pure speculation....

    --roboticus

      Hi everyone,

      This was a real interesting topic, and ++ to all for your great contributions. In the end, I removed tail from the code, and just hard coded a simple perl based tail into my code. That works, plus I don't have to fork another process.

      #!/usr/bin/perl # Known issue # If the file gets truncated, the script will not terminate # ==================================================================== +========= use IO::Handle; autoflush STDOUT; use Fcntl qw(:seek); $file = 'mylog.txt'; $started = 0; #set to 1 if you want the file to start reading from +the start of the logfile while(1) { open LOG, $file or die "$file could not be opened."; seek LOG, $pos, SEEK_SET if defined $pos; while(<LOG>) { chomp; if($started) { print "$_\n"; } } $pos = tell LOG; close LOG; sleep 1; $started = 1; } exit(0);

      Thanks!

           |\/| _. _ _  ._
      www. |  |(_|_>_>\/| | .net
                      /
      
      The more I learn the more I realise I don't know.
      - Albert Einstein

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://550396]
Approved by Zaxo
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (3)
As of 2024-04-25 06:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found