in reply to Re^2: Getting a Perl program to close a command it starts when the perl program exits?
in thread Getting a Perl program to close a command it starts when the perl program exits?

The problem is the order in which the handle's destructor and the END block are executed. If the file handle is destroyed first, you have a problem. When destroying a file handle, perl closes it, and closing a file handle opened with open '...|' causes perl to wait until the child process exits. Seeing as the kill command hasn't been executed, that won't happen.

You don't have that problem with open3 since you control when waitpid is called.

use IPC::Open3 qw( open3 ); my @tail_pids; END { for my $tail_pid (@tail_pids) { kill TERM => $tail_pid; waitpid($tail_pid, 0); } } sub start_tail { my ($mw, $file) = @_; my ($from_tail, $tail_err); push @tail_pids, open3(undef, $from_tail, $tail_err, qw( tail -1lf +), $file); $mw->fileevent($from_tail, 'readable' => [ \&input_from_tail, $mw, +$file ]); $mw->fileevent($tail_err, 'readable' => [ \&sink, $mw, +$file ]); }

Notes:

  • Comment on Re^3: Getting a Perl program to close a command it starts when the perl program exits?
  • Select or Download Code

Replies are listed 'Best First'.
Re^4: Getting a Perl program to close a command it starts when the perl program exits?
by kyle (Abbot) on Aug 29, 2007 at 18:10 UTC

    The problem is the order in which the handle's destructor and the END block are executed. If the file handle is destroyed first, you have a problem. When destroying a file handle, perl closes it, and closing a file handle opened with open '...|' causes perl to wait until the child process exits. Seeing as the kill command hasn't been executed, that won't happen.

    OK, I think I understand now.

    The difference is that when you open the lexical, there's an (IO::Handle) object implicitly created. That object gets a call to DESTROY before the END block is called. The DESTROY method calls close, which has to wait for the subprocess to finish, which it never does.

    In the case of a global file handle, Perl itself will close it after the END block is called. In that case, END can kill the process and everything else goes fine.

    package Foo; sub new { bless {} } sub DESTROY { print "DESTROY()\n" } package main; my $foo = Foo->new(); print "I have a foo.\n"; END { print "END()\n" } exit; __END__ I have a foo. DESTROY() END()

      Yup, that's exactly it. Even more interesting is the difference between lex and pkg vars:

      { package Pkg; sub new { my ($class, $text) = @_; return bless(\$text, $class); } sub DESTROY { my ($self) = @_; print "DESTROY $$self\n"; } } my $lex = Pkg->new('file scope lex var'); our $pkg = Pkg->new('pkg var'); END { print "END\n" } print("At end of script\n");
      At end of script DESTROY file scope lex var END DESTROY pkg var

      I don't know if the order is unchanging. I wouldn't count on it. Doing our $pkg2 = \$lex; or sub test { $lex } would change the order, for example.

Re^4: Getting a Perl program to close a command it starts when the perl program exits?
by BrowserUk (Patriarch) on Aug 29, 2007 at 18:03 UTC
      Check the original post. He is, which is also the reason he can't use File::Tail.