Child-0.009000755003720003720 011435613251 13065 5ustar00exodistexodist000000000000Child-0.009/README000444003720003720 1155411435613251 14130 0ustar00exodistexodist000000000000NAME Child - Object oriented simple interface to fork() DESCRIPTION Fork is too low level, and difficult to manage. Often people forget to exit at the end, reap their children, and check exit status. The problem is the low level functions provided to do these things. Throw in pipes for IPC and you just have a pile of things nobody wants to think about. Child is an Object Oriented interface to fork. It provides a clean way to start a child process, and manage it afterwords. It provides methods for running, waiting, killing, checking, and even communicating with a child process. NOTE: kill() is unpredictable on windows, strawberry perl sends the kill signal to the parent as well as the child. SYNOPSIS BASIC use Child; my $child = Child->new(sub { my ( $parent ) = @_; .... # exit() is called for you at the end. }); my $proc = $child->start # Kill the child if it is not done $proc->complete || $proc->kill(9); $proc->wait; #blocking IPC # Build with IPC my $child2 = Child->new(sub { my $self = shift; $self->say("message1"); $self->say("message2"); my $reply = $self->read(1); }, pipe => 1 ); my $proc2 = $child2->start; # Read (blocking) my $message1 = $proc2->read(); my $message2 = $proc2->read(); $proc2->say("reply"); SHORTCUT Child can export the child() shortcut function when requested. This function creates and starts the child process in one action. use Child qw/child/; my $proc = child { my $parent = shift; ... }; You can also request IPC: use Child qw/child/; my $child = child { my $parent = shift; ... } pipe => 1; DETAILS First you define a child, you do this by constructing a Child object. Defining a child does not start a new process, it is just the way to define what the new process will look like. Once you have defined the child you can start the process by calling $child->start(). One child object can start as many processes as you like. When you start a child an Child::Link::Proc object is returned. This object provides multiple useful methods for interacting with your process. Within the process itself an Child::Link::Parent is created and passed as the only parameter to the function used to define the child. The parent object is how the child interacts with its parent. PROCESS MANAGEMENT METHODS @procs = Child->all_procs() Get a list of all the processes that have been started. This list is cleared in processes when they are started; that is a child will not list its siblings. @pids = Child->all_proc_pids() Get a list of all the pids of processes that have been started. Child->wait_all() Call wait() on all processes. EXPORTS $proc = child( sub { ... } ) $proc = child { ... } $proc = child( sub { ... }, $plugin, @data ) $proc = child { ... } $plugin => @data Create and start a process in one action. CONSTRUCTOR $child = Child->new( sub { ... } ) $child = Child->new( sub { ... }, $plugin, @plugin_data ) Create a new Child object. Does not start the child. OBJECT METHODS $proc = $child->start() Start the child process. SEE ALSO Child::Link::Proc The proc object that is returned by $child->start() Child::Link::Parent The parent object that is provided as the argumunt to the function used to define the child. Child::Link::IPC The base class for IPC plugin link objects. This provides the IPC methods. HISTORY Most of this was part of Parrallel::Runner intended for use in the Fennec project. Fennec is being broken into multiple parts, this is one such part. FENNEC PROJECT This module is part of the Fennec project. See Fennec for more details. Fennec is a project to develop an extendable and powerful testing framework. Together the tools that make up the Fennec framework provide a potent testing environment. The tools provided by Fennec are also useful on their own. Sometimes a tool created for Fennec is useful outside the greator framework. Such tools are turned into their own projects. This is one such project. Fennec - The core framework The primary Fennec project that ties them all together. AUTHORS Chad Granum exodist7@gmail.com COPYRIGHT Copyright (C) 2010 Chad Granum Child is free software; Standard perl licence. Child is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. Child-0.009/Build.PL000444003720003720 127011435613251 14516 0ustar00exodistexodist000000000000#!/usr/bin/perl use 5.006; use strict; use warnings; use Module::Build; my $build = Module::Build->new( module_name => 'Child', license => 'perl', dist_author => 'Chad Granum ', create_readme => 1, requires => { 'POSIX' => 0, 'Exporter' => 5.57, 'perl' => 5.006, }, build_requires => { 'Test::More' => 0.88, }, meta_merge => { resources => { repository => 'http://github.com/exodist/Child', bugtracker => 'http://github.com/exodist/Child/issues', homepage => 'http://open-exodus.net/projects/child' }, } ); $build->create_build_script; Child-0.009/META.yml000444003720003720 224511435613251 14476 0ustar00exodistexodist000000000000--- abstract: 'Object oriented simple interface to fork()' author: - 'Chad Granum ' build_requires: Test::More: 0.88 configure_requires: Module::Build: 0.36 generated_by: 'Module::Build version 0.3607' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: Child provides: Child: file: lib/Child.pm version: 0.009 Child::IPC::Pipe: file: lib/Child/IPC/Pipe.pm Child::Link: file: lib/Child/Link.pm Child::Link::IPC: file: lib/Child/Link/IPC.pm Child::Link::IPC::Pipe: file: lib/Child/Link/IPC/Pipe.pm Child::Link::IPC::Pipe::Parent: file: lib/Child/Link/IPC/Pipe/Parent.pm Child::Link::IPC::Pipe::Proc: file: lib/Child/Link/IPC/Pipe/Proc.pm Child::Link::Parent: file: lib/Child/Link/Parent.pm Child::Link::Proc: file: lib/Child/Link/Proc.pm Child::Util: file: lib/Child/Util.pm requires: Exporter: 5.57 POSIX: 0 perl: 5.006 resources: bugtracker: http://github.com/exodist/Child/issues homepage: http://open-exodus.net/projects/child license: http://dev.perl.org/licenses/ repository: http://github.com/exodist/Child version: 0.009 Child-0.009/MANIFEST000444003720003720 50111435613251 14327 0ustar00exodistexodist000000000000Build.PL lib/Child.pm lib/Child/IPC/Pipe.pm lib/Child/Link.pm lib/Child/Link/IPC.pm lib/Child/Link/IPC/Pipe.pm lib/Child/Link/IPC/Pipe/Parent.pm lib/Child/Link/IPC/Pipe/Proc.pm lib/Child/Link/Parent.pm lib/Child/Link/Proc.pm lib/Child/Util.pm MANIFEST This list of files META.yml README t/Child.t t/Import.t t/Manage.t Child-0.009/t000755003720003720 011435613251 13330 5ustar00exodistexodist000000000000Child-0.009/t/Manage.t000444003720003720 114611435613251 15044 0ustar00exodistexodist000000000000#!/usr/bin/perl; use strict; use warnings; use Test::More 0.88; our $CLASS = 'Child'; require_ok( $CLASS ); my @children = map { $CLASS->new(sub { 1 }) } 1 .. 4; my @get = $CLASS->all_procs; is( @get, 0, "0 children started" ); my @all; push @all => $_->start for @children; @get = $CLASS->all_procs; is( @get, 4, "4 children" ); is_deeply( \@get, \@all, "Exact list" ); is_deeply( [ $CLASS->all_proc_pids ], [ map { $_->pid } @all ], "pids" ); is( $_->exit(), undef, "Not waited " . $_->pid ) for @all; $CLASS->wait_all(); ok( defined($_->exit()), "waited " . $_->pid ) for @all; done_testing; Child-0.009/t/Child.t000444003720003720 435511435613251 14704 0ustar00exodistexodist000000000000#!/usr/bin/perl; use strict; use warnings; use Test::More 0.88; our $CLASS = 'Child'; require_ok( $CLASS ); my $child = $CLASS->new( sub { my $self = shift; $self->say( "Have self" ); $self->say( "parent: " . $self->pid ); my $in = $self->read(); $self->say( $in ); }, pipe => 1 ); my $proc = $child->start; is( $proc->read(), "Have self\n", "child has self" ); is( $proc->read(), "parent: $$\n", "child has parent PID" ); { local $SIG{ALRM} = sub { die "non-blocking timeout" }; alarm 5; ok( !$proc->is_complete, "Not Complete" ); alarm 0; } $proc->say("XXX"); is( $proc->read(), "XXX\n", "Full IPC" ); ok( $proc->wait, "wait" ); ok( $proc->is_complete, "Complete" ); is( $proc->exit_status, 0, "Exit clean" ); $proc = $CLASS->new( sub { sleep 15 } )->start; my $ret = eval { $proc->say("XXX"); 1 }; ok( !$ret, "Died, no IPC" ); like( $@, qr/Child was created without IPC support./, "No IPC" ); if ( $^O eq 'MSWin32' ) { diag( "on win32 we must wait on this process (15 seconds)" ); $proc->wait; } else { $proc->kill(2); } $proc = $CLASS->new( sub { my $self = shift; $SIG{INT} = sub { exit( 2 ) }; $self->say( "go" ); sleep 15; exit 2; }, pipe => 1 )->start; $proc->read; sleep 1; if ( $^O eq 'MSWin32' ) { diag( "on win32 we must wait on this process (15 seconds)" ); $proc->wait; } else { ok( $proc->kill(2), "Send signal" ); ok( !$proc->wait, "wait" ); } ok( $proc->is_complete, "Complete" ); is( $proc->exit_status, 2, "Exit 2" ); ok( $proc->unix_exit > 2, "Real exit" ); $child = $CLASS->new( sub { my $self = shift; $self->autoflush(0); $self->say( "A" ); $self->flush; $self->say( "B" ); sleep 5; $self->flush; }, pipe => 1 ); $proc = $child->start; is( $proc->read(), "A\n", "A" ); my $start = time; is( $proc->read(), "B\n", "B" ); my $end = time; ok( $end - $start > 2, "No autoflush" ); SKIP: { if ($^O eq 'MSWin32') { skip "detach is not available on win32", 1; } else { $proc = $CLASS->new( sub { my $self = shift; $self->detach; $self->say( $self->detached ); }, pipe => 1 )->start; is( $proc->read(), $proc->pid . "\n", "Child detached" ); } } done_testing; Child-0.009/t/Import.t000444003720003720 62011435613251 15102 0ustar00exodistexodist000000000000#!/usr/bin/perl; use strict; use warnings; use Test::More 0.88; our $CLASS = 'Child'; require_ok( $CLASS ); $CLASS->import(); ok( ! __PACKAGE__->can('child'), "No export by default" ); $CLASS->import('child'); can_ok( __PACKAGE__, 'child' ); my $one = child( sub { 1 }); ok( !$one->ipc, "no ipc by default" ); $one = child( sub { 1 }, pipe => 1 ); ok( $one->ipc, "ipc by param" ); done_testing; Child-0.009/lib000755003720003720 011435613251 13633 5ustar00exodistexodist000000000000Child-0.009/lib/Child.pm000444003720003720 1421211435613251 15371 0ustar00exodistexodist000000000000package Child; use 5.006; use strict; use warnings; use Carp; use Child::Util; use Child::Link::Proc; use Child::Link::Parent; use Exporter 'import'; our $VERSION = "0.009"; our @PROCS; our @EXPORT_OK = qw/child/; add_accessors qw/code/; sub child(&;@) { my ( $code, @params ) = @_; my $caller = caller; return __PACKAGE__->new( $code, @params )->start; } sub all_procs { @PROCS } sub all_proc_pids { my $class = shift; map { $_->pid } $class->all_procs; } sub wait_all { my $class = shift; $_->wait() for $class->all_procs; } sub new { my ( $class, $code, $plugin, @data ) = @_; return bless( { _code => $code }, $class ) unless $plugin; my $build = __PACKAGE__; $build .= '::IPC::' . ucfirst $plugin; eval "require $build; 1" || croak( "Could not load plugin '$plugin': $@" ); return $build->new( $code, @data ); } sub shared_data {} sub child_class { 'Child::Link::Proc' } sub parent_class { 'Child::Link::Parent' } sub start { my $self = shift; my $ppid = $$; my @data = $self->shared_data; if ( my $pid = fork() ) { my $proc = $self->child_class->new( $pid, @data ); push @PROCS => $proc; return $proc; } # In the child @PROCS = (); my $parent = $self->parent_class->new( $ppid, @data ); my $code = $self->code; $code->( $parent ); exit; } 1; __END__ =head1 NAME Child - Object oriented simple interface to fork() =head1 DESCRIPTION Fork is too low level, and difficult to manage. Often people forget to exit at the end, reap their children, and check exit status. The problem is the low level functions provided to do these things. Throw in pipes for IPC and you just have a pile of things nobody wants to think about. Child is an Object Oriented interface to fork. It provides a clean way to start a child process, and manage it afterwords. It provides methods for running, waiting, killing, checking, and even communicating with a child process. B: kill() is unpredictable on windows, strawberry perl sends the kill signal to the parent as well as the child. =head1 SYNOPSIS =head2 BASIC use Child; my $child = Child->new(sub { my ( $parent ) = @_; .... # exit() is called for you at the end. }); my $proc = $child->start # Kill the child if it is not done $proc->complete || $proc->kill(9); $proc->wait; #blocking =head2 IPC # Build with IPC my $child2 = Child->new(sub { my $self = shift; $self->say("message1"); $self->say("message2"); my $reply = $self->read(1); }, pipe => 1 ); my $proc2 = $child2->start; # Read (blocking) my $message1 = $proc2->read(); my $message2 = $proc2->read(); $proc2->say("reply"); =head2 SHORTCUT Child can export the child() shortcut function when requested. This function creates and starts the child process in one action. use Child qw/child/; my $proc = child { my $parent = shift; ... }; You can also request IPC: use Child qw/child/; my $child = child { my $parent = shift; ... } pipe => 1; =head1 DETAILS First you define a child, you do this by constructing a L object. Defining a child does not start a new process, it is just the way to define what the new process will look like. Once you have defined the child you can start the process by calling $child->start(). One child object can start as many processes as you like. When you start a child an L object is returned. This object provides multiple useful methods for interacting with your process. Within the process itself an L is created and passed as the only parameter to the function used to define the child. The parent object is how the child interacts with its parent. =head1 PROCESS MANAGEMENT METHODS =over 4 =item @procs = Child->all_procs() Get a list of all the processes that have been started. This list is cleared in processes when they are started; that is a child will not list its siblings. =item @pids = Child->all_proc_pids() Get a list of all the pids of processes that have been started. =item Child->wait_all() Call wait() on all processes. =back =head1 EXPORTS =over 4 =item $proc = child( sub { ... } ) =item $proc = child { ... } =item $proc = child( sub { ... }, $plugin, @data ) =item $proc = child { ... } $plugin => @data Create and start a process in one action. =back =head1 CONSTRUCTOR =over 4 =item $child = Child->new( sub { ... } ) =item $child = Child->new( sub { ... }, $plugin, @plugin_data ) Create a new Child object. Does not start the child. =back =head1 OBJECT METHODS =over =item $proc = $child->start() Start the child process. =back =head1 SEE ALSO =over 4 =item L The proc object that is returned by $child->start() =item L The parent object that is provided as the argumunt to the function used to define the child. =item L The base class for IPC plugin link objects. This provides the IPC methods. =back =head1 HISTORY Most of this was part of L intended for use in the L project. Fennec is being broken into multiple parts, this is one such part. =head1 FENNEC PROJECT This module is part of the Fennec project. See L for more details. Fennec is a project to develop an extendable and powerful testing framework. Together the tools that make up the Fennec framework provide a potent testing environment. The tools provided by Fennec are also useful on their own. Sometimes a tool created for Fennec is useful outside the greator framework. Such tools are turned into their own projects. This is one such project. =over 2 =item L - The core framework The primary Fennec project that ties them all together. =back =head1 AUTHORS Chad Granum L =head1 COPYRIGHT Copyright (C) 2010 Chad Granum Child is free software; Standard perl licence. Child is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. Child-0.009/lib/Child000755003720003720 011435613251 14656 5ustar00exodistexodist000000000000Child-0.009/lib/Child/Util.pm000444003720003720 372111435613251 16271 0ustar00exodistexodist000000000000package Child::Util; use strict; use warnings; use Carp qw/croak/; use Exporter 'import'; our @EXPORT = qw/add_accessors add_abstract/; sub _abstract { my $class = shift; croak "$class does not implement this function." } sub add_abstract { my $caller = caller; no strict 'refs'; *{"$caller\::$_"} = \&_abstract for @_; } sub add_accessors { my $class = caller; _add_accessor( $class, $_ ) for @_; } sub _add_accessor { my ( $class, $reader ) = @_; my $prop = "_$reader"; my $psub = sub { my $self = shift; ($self->{ $prop }) = @_ if @_; return $self->{ $prop }; }; my $rsub = sub { my $self = shift; return $self->$prop(); }; no strict 'refs'; *{"$class\::$reader"} = $rsub; *{"$class\::$prop"} = $psub; } 1; =head1 NAME Child::Util - Utility functions for L>Child> =head1 HISTORY Most of this was part of L intended for use in the L project. Fennec is being broken into multiple parts, this is one such part. =head1 FENNEC PROJECT This module is part of the Fennec project. See L for more details. Fennec is a project to develop an extendable and powerful testing framework. Together the tools that make up the Fennec framework provide a potent testing environment. The tools provided by Fennec are also useful on their own. Sometimes a tool created for Fennec is useful outside the greator framework. Such tools are turned into their own projects. This is one such project. =over 2 =item L - The core framework The primary Fennec project that ties them all together. =back =head1 AUTHORS Chad Granum L =head1 COPYRIGHT Copyright (C) 2010 Chad Granum Child is free software; Standard perl licence. Child is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. Child-0.009/lib/Child/Link.pm000444003720003720 313111435613251 16244 0ustar00exodistexodist000000000000package Child::Link; use strict; use warnings; use Child::Util; use Carp qw/croak/; add_accessors qw/pid/; sub ipc { undef } sub _no_ipc { croak "Child was created without IPC support" } sub new { my $class = shift; my ( $pid ) = @_; return bless( { _pid => $pid }, $class ); } { no strict 'refs'; *{__PACKAGE__ . '::' . $_} = \&_no_ipc for qw/autoflush flush read say write/; } 1; =head1 NAME Child::Link - Base class for objects that link child and parent processes. =head1 HISTORY Most of this was part of L intended for use in the L project. Fennec is being broken into multiple parts, this is one such part. =head1 FENNEC PROJECT This module is part of the Fennec project. See L for more details. Fennec is a project to develop an extendable and powerful testing framework. Together the tools that make up the Fennec framework provide a potent testing environment. The tools provided by Fennec are also useful on their own. Sometimes a tool created for Fennec is useful outside the greator framework. Such tools are turned into their own projects. This is one such project. =over 2 =item L - The core framework The primary Fennec project that ties them all together. =back =head1 AUTHORS Chad Granum L =head1 COPYRIGHT Copyright (C) 2010 Chad Granum Child is free software; Standard perl licence. Child is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. Child-0.009/lib/Child/IPC000755003720003720 011435613251 15271 5ustar00exodistexodist000000000000Child-0.009/lib/Child/IPC/Pipe.pm000444003720003720 332111435613251 16660 0ustar00exodistexodist000000000000package Child::IPC::Pipe; use strict; use warnings; use Child::Link::IPC::Pipe::Proc; use Child::Link::IPC::Pipe::Parent; use base 'Child'; sub child_class { 'Child::Link::IPC::Pipe::Proc' } sub parent_class { 'Child::Link::IPC::Pipe::Parent' } sub shared_data { pipe( my ( $ain, $aout )); pipe( my ( $bin, $bout )); return [ [ $ain, $aout ], [ $bin, $bout ], ]; } sub new { my ( $class, $code ) = @_; return bless( { _code => $code }, $class ); } 1; =head1 NAME Child::IPC::Pipe - Pipe based IPC plugin for L =head1 DESCRIPTION Creates 2 pipes just before forking. =head1 HISTORY Most of this was part of L intended for use in the L project. Fennec is being broken into multiple parts, this is one such part. =head1 FENNEC PROJECT This module is part of the Fennec project. See L for more details. Fennec is a project to develop an extendable and powerful testing framework. Together the tools that make up the Fennec framework provide a potent testing environment. The tools provided by Fennec are also useful on their own. Sometimes a tool created for Fennec is useful outside the greator framework. Such tools are turned into their own projects. This is one such project. =over 2 =item L - The core framework The primary Fennec project that ties them all together. =back =head1 AUTHORS Chad Granum L =head1 COPYRIGHT Copyright (C) 2010 Chad Granum Child is free software; Standard perl licence. Child is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. Child-0.009/lib/Child/Link000755003720003720 011435613251 15553 5ustar00exodistexodist000000000000Child-0.009/lib/Child/Link/IPC.pm000444003720003720 615411435613251 16667 0ustar00exodistexodist000000000000package Child::Link::IPC; use strict; use warnings; use Child::Util; use base 'Child::Link'; add_accessors qw/ipc/; add_abstract qw/ read_handle write_handle /; sub init {} sub new { my $class = shift; my ( $pid, @shared ) = @_; my $self = $class->SUPER::new($pid); $self->init( @shared ); return $self; } sub autoflush { my $self = shift; my ( $value ) = @_; my $write = $self->write_handle; my $selected = select( $write ); $| = $value if @_; my $out = $|; select( $selected ); return $out; } sub flush { my $self = shift; my $orig = $self->autoflush(); $self->autoflush(1); my $write = $self->write_handle; $self->autoflush($orig); } sub read { my $self = shift; my $handle = $self->read_handle; return <$handle>; } sub say { my $self = shift; $self->write( map {$_ . $/} @_ ); } sub write { my $self = shift; my $handle = $self->write_handle; print $handle @_; } 1; =head1 NAME Child::Link::IPC - Base class for process links that provide IPC. =head1 SEE ALSO This class inherits from: =over 4 =item L =back =head1 METHODS =over 4 =item $proc->new( $pid. @shared ) Constructor =item $proc->read() Read a message from the child. =item $proc->write( @MESSAGES ) Send the messages to the child. works like print, you must add "\n". =item $proc->say( @MESSAGES ) Send the messages to the child. works like say, adds the seperator for you (usually "\n"). =item $proc->autoflush( $BOOL ) Turn autoflush on/off for the current processes write handle. This is on by default. =item $proc->flush() Flush the current processes write handle. =item $proc->ipc() =item $proc->_ipc( $new ) Accessors for you to use or ignore. =back =head1 ABSTRACT METHODS =over 4 =item $proc->read_handle() Should return a read handle for reading from the child. =item $proc->write_handle() Should return a write handle for writing to the child. =item $proc->init( @shared ) Called by new during construction =back =head1 HISTORY Most of this was part of L intended for use in the L project. Fennec is being broken into multiple parts, this is one such part. =head1 FENNEC PROJECT This module is part of the Fennec project. See L for more details. Fennec is a project to develop an extendable and powerful testing framework. Together the tools that make up the Fennec framework provide a potent testing environment. The tools provided by Fennec are also useful on their own. Sometimes a tool created for Fennec is useful outside the greator framework. Such tools are turned into their own projects. This is one such project. =over 2 =item L - The core framework The primary Fennec project that ties them all together. =back =head1 AUTHORS Chad Granum L =head1 COPYRIGHT Copyright (C) 2010 Chad Granum Child is free software; Standard perl licence. Child is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. Child-0.009/lib/Child/Link/Proc.pm000444003720003720 734411435613251 17161 0ustar00exodistexodist000000000000package Child::Link::Proc; use strict; use warnings; use Carp; use Carp; use Child::Util; use base 'Child::Link'; add_accessors qw/exit/; sub is_complete { my $self = shift; $self->_wait(); return defined($self->exit); } sub wait { my $self = shift; return unless $self->_wait(1); return !$self->exit; } sub exit_status { my $self = shift; return unless $self->is_complete; return ($self->exit >> 8); } sub unix_exit { my $self = shift; return unless $self->is_complete; return $self->exit; } sub _wait { my $self = shift; my ( $block ) = @_; #non-blocking to check if process was terminated #blocking to wait until it finishes unless ( defined $self->exit ) { my @flags; require POSIX unless $block; my $ret; my $x = 1; do { sleep(1) if defined $ret; $ret = waitpid( $self->pid, $block ? 0 : &POSIX::WNOHANG ); } while ( $block && !$ret ); return 0 unless $ret; if ($^O eq 'MSWin32') { croak( "wait returned $ret: No such process " . $self->pid ) if $ret == -1; #forked threads on Win32 have negative pids } else { croak( "wait returned $ret: No such process " . $self->pid ) if $ret < 0; } $self->_exit( $? ); } return defined($self->exit); } sub kill { my $self = shift; my ( $sig ) = @_; kill( $sig, $self->pid ); } 1; =head1 NAME Child::Link::Proc - Proc object used by L. =head1 SEE ALSO This class inherits from: =over 4 =item L =back =head1 METHODS =over 4 =item $bool = $proc->is_complete() Check if the child is finished (non-blocking) =item $proc->wait() Wait until child terminates, destroy remaining zombie process (blocking) =item $proc->kill($SIG) Send the $SIG signal to the child process. B: kill() is unpredictable on windows, strawberry perl sends the kill signal to the parent as well as the child. =item $proc->pid() Returns the process PID. =item $proc->exit_status() Will be undef unless the process has exited, otherwise it will have the exit status. B: When you call exit($N) the actual unix exit status will be bit shifed with extra information added. exit_status() will shift the value back for you. That means exit_status() will return 2 whun your child calls exit(2) see unix_exit() if you want the actual value wait() assigned to $?. =item $proc->unix_exit() When you call exit($N) the actual unix exit status will be bit shifed with extra information added. See exit_status() if you want the actual value used in exit() in the child. =back =head1 HISTORY Most of this was part of L intended for use in the L project. Fennec is being broken into multiple parts, this is one such part. =head1 FENNEC PROJECT This module is part of the Fennec project. See L for more details. Fennec is a project to develop an extendable and powerful testing framework. Together the tools that make up the Fennec framework provide a potent testing environment. The tools provided by Fennec are also useful on their own. Sometimes a tool created for Fennec is useful outside the greator framework. Such tools are turned into their own projects. This is one such project. =over 2 =item L - The core framework The primary Fennec project that ties them all together. =back =head1 AUTHORS Chad Granum L =head1 COPYRIGHT Copyright (C) 2010 Chad Granum Child is free software; Standard perl licence. Child is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. Child-0.009/lib/Child/Link/Parent.pm000444003720003720 327511435613251 17506 0ustar00exodistexodist000000000000package Child::Link::Parent; use strict; use warnings; use Child::Util; use base 'Child::Link'; add_accessors qw/detached/; sub detach { my $self = shift; require POSIX; $self->_detached( POSIX::setsid() ) || die "Cannot detach from parent $!"; } 1; =head1 NAME Child::Link::Proc - Proc object used by L. =head1 SEE ALSO This class inherits from: =over 4 =item L =back =head1 METHODS =over 4 =item $proc->pid() Returns the parent process PID. =item $proc->detach() Detach the from the parent. uses POSIX::setsid(). Not available in windows. =back =head1 HISTORY Most of this was part of L intended for use in the L project. Fennec is being broken into multiple parts, this is one such part. =head1 FENNEC PROJECT This module is part of the Fennec project. See L for more details. Fennec is a project to develop an extendable and powerful testing framework. Together the tools that make up the Fennec framework provide a potent testing environment. The tools provided by Fennec are also useful on their own. Sometimes a tool created for Fennec is useful outside the greator framework. Such tools are turned into their own projects. This is one such project. =over 2 =item L - The core framework The primary Fennec project that ties them all together. =back =head1 AUTHORS Chad Granum L =head1 COPYRIGHT Copyright (C) 2010 Chad Granum Child is free software; Standard perl licence. Child is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. Child-0.009/lib/Child/Link/IPC000755003720003720 011435613251 16166 5ustar00exodistexodist000000000000Child-0.009/lib/Child/Link/IPC/Pipe.pm000444003720003720 336211435613251 17562 0ustar00exodistexodist000000000000package Child::Link::IPC::Pipe; use strict; use warnings; use Child::Util; use base 'Child::Link::IPC'; add_abstract qw/cross_pipes/; sub read_handle { shift->ipc->[0] } sub write_handle { shift->ipc->[1] } sub init { my $self = shift; my ($pipes) = @_; $pipes = [ $pipes->[1], $pipes->[0], ] if $self->cross_pipes; $self->_ipc([ $pipes->[0]->[0], $pipes->[1]->[1], ]); $self->autoflush(1); } 1; =head1 NAME Child::Link::IPC::Pipe - Base class for link objects used by the L plugin. =head1 SEE ALSO This class inherits from: =over 4 =item L =back =head1 HISTORY Most of this was part of L intended for use in the L project. Fennec is being broken into multiple parts, this is one such part. =head1 FENNEC PROJECT This module is part of the Fennec project. See L for more details. Fennec is a project to develop an extendable and powerful testing framework. Together the tools that make up the Fennec framework provide a potent testing environment. The tools provided by Fennec are also useful on their own. Sometimes a tool created for Fennec is useful outside the greator framework. Such tools are turned into their own projects. This is one such project. =over 2 =item L - The core framework The primary Fennec project that ties them all together. =back =head1 AUTHORS Chad Granum L =head1 COPYRIGHT Copyright (C) 2010 Chad Granum Child is free software; Standard perl licence. Child is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. Child-0.009/lib/Child/Link/IPC/Pipe000755003720003720 011435613251 17063 5ustar00exodistexodist000000000000Child-0.009/lib/Child/Link/IPC/Pipe/Proc.pm000444003720003720 276511435613251 20473 0ustar00exodistexodist000000000000package Child::Link::IPC::Pipe::Proc; use strict; use warnings; use Child::Util; use base qw/ Child::Link::IPC::Pipe Child::Link::Proc /; sub cross_pipes { 0 }; 1; =head1 NAME Child::Link::IPC::Pipe::Proc - Proc object used by the pipe plugin. =head1 SEE ALSO This class inherits from: =over 4 =item L =item L =item L =back =head1 HISTORY Most of this was part of L intended for use in the L project. Fennec is being broken into multiple parts, this is one such part. =head1 FENNEC PROJECT This module is part of the Fennec project. See L for more details. Fennec is a project to develop an extendable and powerful testing framework. Together the tools that make up the Fennec framework provide a potent testing environment. The tools provided by Fennec are also useful on their own. Sometimes a tool created for Fennec is useful outside the greator framework. Such tools are turned into their own projects. This is one such project. =over 2 =item L - The core framework The primary Fennec project that ties them all together. =back =head1 AUTHORS Chad Granum L =head1 COPYRIGHT Copyright (C) 2010 Chad Granum Child is free software; Standard perl licence. Child is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. Child-0.009/lib/Child/Link/IPC/Pipe/Parent.pm000444003720003720 277711435613251 21024 0ustar00exodistexodist000000000000package Child::Link::IPC::Pipe::Parent; use strict; use warnings; use Child::Util; use base qw/ Child::Link::IPC::Pipe Child::Link::Parent /; sub cross_pipes { 1 }; 1; =head1 NAME Child::Link::IPC::Pipe::Parent - Parent object used by the pipe plugin. =head1 SEE ALSO This class inherits from: =over 4 =item L =item L =item L =back =head1 HISTORY Most of this was part of L intended for use in the L project. Fennec is being broken into multiple parts, this is one such part. =head1 FENNEC PROJECT This module is part of the Fennec project. See L for more details. Fennec is a project to develop an extendable and powerful testing framework. Together the tools that make up the Fennec framework provide a potent testing environment. The tools provided by Fennec are also useful on their own. Sometimes a tool created for Fennec is useful outside the greator framework. Such tools are turned into their own projects. This is one such project. =over 2 =item L - The core framework The primary Fennec project that ties them all together. =back =head1 AUTHORS Chad Granum L =head1 COPYRIGHT Copyright (C) 2010 Chad Granum Child is free software; Standard perl licence. Child is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.