http://qs321.pair.com?node_id=373937

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

I'm using Test::Cmd to test a daemon. Part of this testing requires forking off a process in the test scripts to simulate a file growing (as through FTP). I've had the darndest time figuring out how to get this to work with Test::Cmd, because the child process would clean up the environment when it exited. I've figured out a solution, which is pop @{$test->{cleanup}}; in the child process. However, that came about by reading the source.

Anyone familiar enough with the API to provide a non-internals-mucking solution to this?

------
We are the carpenters and bricklayers of the Information Age.

Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

I shouldn't have to say this, but any code, unless otherwise stated, is untested

Replies are listed 'Best First'.
Re: Test::Cmd and forking
by chromatic (Archbishop) on Jul 13, 2004 at 16:49 UTC

    If you're not terribly worried about resource cleanup, there's always POSIX::_exit():

    #!/usr/bin/perl -w use strict; use POSIX (); END { warn "Exiting $$\n"; } die "Couldn't fork\n" unless defined( my $pid = fork() ); if ($pid) { print "Parent is $$, child is $pid\n"; } else { print "Child is $$\n"; POSIX::_exit( 0 ); }
Re: Test::Cmd and forking
by DrWhy (Chaplain) on Jul 13, 2004 at 15:30 UTC
    I ran into a similar problem myself in my own test code where I didn't want some END blocks to get executed in the child. There are several possibilities to avoid cleanup code when a forked child exits. I thought of a couple (I bet there's more than two ways to do this though). I'm not really satisfied with either of these though.

    1. Rather than exit or die in the child, exec something innocuous, e.g.:

      exec('/bin/true') or exec('perl','-e','')

    2. Another possibility which I thought of but did not test is to have the child send itself a SIGKILL (or maybe a SIGTERM) would be enough?)
      You can use Manip::END to selectively delete END blocks. It was written precisely for your situation where you have a fork and a troublesome END block.
      $ends = Manip::END->new; # now remove some END blocks $ends->remove_class("Test::Cmd"); # only those in Test::Cmd $ends->remove_isa("Test::Cmd"); # in Test::Cmd and any subclasses $ends->remove_pat('^Test::Cmd(::.*)?$'); # any END blocks from Test::C +md and Test::Cmd::Whatever
      You can also do other manipulations.