From 653a88a1b53ce6165ef4aa7c8cddefa1371c351a Mon Sep 17 00:00:00 2001 From: scm Date: Mon, 11 Sep 2017 14:51:55 +0800 Subject: [PATCH] Init libparallel-forkmanager-perl Change-Id: I93f1c84ed036116c3538adc825b4624f8745d826 Signed-off-by: scm --- Parallel-ForkManager-1.17/CONTRIBUTORS | 12 + Parallel-ForkManager-1.17/Changes | 131 +++ Parallel-ForkManager-1.17/INSTALL | 43 + Parallel-ForkManager-1.17/MANIFEST | 30 + Parallel-ForkManager-1.17/META.json | 84 ++ Parallel-ForkManager-1.17/META.yml | 45 + Parallel-ForkManager-1.17/MYMETA.json | 88 ++ Parallel-ForkManager-1.17/MYMETA.yml | 45 + Parallel-ForkManager-1.17/Makefile | 877 ++++++++++++++++++ Parallel-ForkManager-1.17/Makefile.PL | 70 ++ Parallel-ForkManager-1.17/README.mkdn | 537 +++++++++++ Parallel-ForkManager-1.17/SIGNATURE | 52 ++ Parallel-ForkManager-1.17/blib/arch/.exists | 0 .../arch/auto/Parallel/ForkManager/.exists | 0 Parallel-ForkManager-1.17/blib/bin/.exists | 0 .../blib/lib/Parallel/.exists | 0 .../blib/lib/Parallel/ForkManager.pm | 852 +++++++++++++++++ .../lib/auto/Parallel/ForkManager/.exists | 0 Parallel-ForkManager-1.17/blib/man1/.exists | 0 Parallel-ForkManager-1.17/blib/man3/.exists | 0 .../blib/man3/Parallel::ForkManager.3pm | 680 ++++++++++++++ Parallel-ForkManager-1.17/blib/script/.exists | 0 Parallel-ForkManager-1.17/cpanfile | 33 + Parallel-ForkManager-1.17/doap.xml | 231 +++++ .../examples/callback.pl | 48 + .../examples/callback_data.pl | 42 + .../examples/parallel_get.pl | 32 + .../lib/Parallel/ForkManager.pm | 852 +++++++++++++++++ Parallel-ForkManager-1.17/pm_to_blib | 0 Parallel-ForkManager-1.17/t/00-compile.t | 51 + Parallel-ForkManager-1.17/t/00-load.t | 41 + .../t/00-report-prereqs.dd | 43 + .../t/00-report-prereqs.t | 183 ++++ Parallel-ForkManager-1.17/t/01-utf8-all.t | 24 + Parallel-ForkManager-1.17/t/02-callback.t | 22 + .../t/03-callback-data.t | 29 + Parallel-ForkManager-1.17/t/basic-methods.t | 38 + Parallel-ForkManager-1.17/t/callback.txt | 26 + Parallel-ForkManager-1.17/t/callback_data.txt | 5 + .../t/waitpid-conflict.t | 38 + .../t/waitpid-waitonechild.t | 42 + .../t/waitpid_blocking.t | 31 + .../xt/release/pause-permissions.t | 13 + .../xt/release/unused-vars.t | 14 + packaging/libparallel-forkmanager-perl.spec | 118 +++ 45 files changed, 5502 insertions(+) create mode 100644 Parallel-ForkManager-1.17/CONTRIBUTORS create mode 100644 Parallel-ForkManager-1.17/Changes create mode 100644 Parallel-ForkManager-1.17/INSTALL create mode 100644 Parallel-ForkManager-1.17/MANIFEST create mode 100644 Parallel-ForkManager-1.17/META.json create mode 100644 Parallel-ForkManager-1.17/META.yml create mode 100644 Parallel-ForkManager-1.17/MYMETA.json create mode 100644 Parallel-ForkManager-1.17/MYMETA.yml create mode 100644 Parallel-ForkManager-1.17/Makefile create mode 100644 Parallel-ForkManager-1.17/Makefile.PL create mode 100644 Parallel-ForkManager-1.17/README.mkdn create mode 100644 Parallel-ForkManager-1.17/SIGNATURE create mode 100644 Parallel-ForkManager-1.17/blib/arch/.exists create mode 100644 Parallel-ForkManager-1.17/blib/arch/auto/Parallel/ForkManager/.exists create mode 100644 Parallel-ForkManager-1.17/blib/bin/.exists create mode 100644 Parallel-ForkManager-1.17/blib/lib/Parallel/.exists create mode 100644 Parallel-ForkManager-1.17/blib/lib/Parallel/ForkManager.pm create mode 100644 Parallel-ForkManager-1.17/blib/lib/auto/Parallel/ForkManager/.exists create mode 100644 Parallel-ForkManager-1.17/blib/man1/.exists create mode 100644 Parallel-ForkManager-1.17/blib/man3/.exists create mode 100644 Parallel-ForkManager-1.17/blib/man3/Parallel::ForkManager.3pm create mode 100644 Parallel-ForkManager-1.17/blib/script/.exists create mode 100644 Parallel-ForkManager-1.17/cpanfile create mode 100644 Parallel-ForkManager-1.17/doap.xml create mode 100755 Parallel-ForkManager-1.17/examples/callback.pl create mode 100644 Parallel-ForkManager-1.17/examples/callback_data.pl create mode 100755 Parallel-ForkManager-1.17/examples/parallel_get.pl create mode 100644 Parallel-ForkManager-1.17/lib/Parallel/ForkManager.pm create mode 100644 Parallel-ForkManager-1.17/pm_to_blib create mode 100644 Parallel-ForkManager-1.17/t/00-compile.t create mode 100644 Parallel-ForkManager-1.17/t/00-load.t create mode 100644 Parallel-ForkManager-1.17/t/00-report-prereqs.dd create mode 100644 Parallel-ForkManager-1.17/t/00-report-prereqs.t create mode 100644 Parallel-ForkManager-1.17/t/01-utf8-all.t create mode 100644 Parallel-ForkManager-1.17/t/02-callback.t create mode 100644 Parallel-ForkManager-1.17/t/03-callback-data.t create mode 100644 Parallel-ForkManager-1.17/t/basic-methods.t create mode 100644 Parallel-ForkManager-1.17/t/callback.txt create mode 100644 Parallel-ForkManager-1.17/t/callback_data.txt create mode 100644 Parallel-ForkManager-1.17/t/waitpid-conflict.t create mode 100644 Parallel-ForkManager-1.17/t/waitpid-waitonechild.t create mode 100644 Parallel-ForkManager-1.17/t/waitpid_blocking.t create mode 100644 Parallel-ForkManager-1.17/xt/release/pause-permissions.t create mode 100644 Parallel-ForkManager-1.17/xt/release/unused-vars.t create mode 100644 packaging/libparallel-forkmanager-perl.spec diff --git a/Parallel-ForkManager-1.17/CONTRIBUTORS b/Parallel-ForkManager-1.17/CONTRIBUTORS new file mode 100644 index 0000000..07338b5 --- /dev/null +++ b/Parallel-ForkManager-1.17/CONTRIBUTORS @@ -0,0 +1,12 @@ + +# PARALLEL-FORKMANAGER CONTRIBUTORS # + +This is the (likely incomplete) list of people who have helped +make this distribution what it is, either via code contributions, +patches, bug reports, help with troubleshooting, etc. A huge +'thank you' to all of them. + + * Ninebit + * Shlomi Fish + + diff --git a/Parallel-ForkManager-1.17/Changes b/Parallel-ForkManager-1.17/Changes new file mode 100644 index 0000000..b6b220d --- /dev/null +++ b/Parallel-ForkManager-1.17/Changes @@ -0,0 +1,131 @@ +Revision history for Perl extension Parallel::ForkManager. + +1.17 2015-11-28 + - Up Test::More's dependency version to v0.94 (because of 'subtest'). + (GH#8, mauke) + + [ STATISTICS ] + - code churn: 3 files changed, 88 insertions(+), 70 deletions(-) + +1.16 2015-10-08 + - wait_one_child wasn't waiting at all. (RT#107634, Slaven Rezic, Yanick) + + [ STATISTICS ] + - code churn: 10 files changed, 517 insertions(+), 461 deletions(-) + +1.15 2015-07-08 + - test's watchdog actually exit if it's being hit. (RT#105747, Zefram) + - condition to catch children reaped by external forces improved. + (RT#105748, Zefram + Yanick) + +1.14 2015-05-17 + - Add 'reap_finished_children', 'is_child' and 'is_parent'. (GH#6, Nine + bit) + +1.13 2015-05-11 + - Use 'select' instead of sleep in _waitpid_blocking. (GH#5) + +1.12 2015-02-23 + - Allow to use true blocking calls. (RT#102305) + +1.11 2015-01-30 + - Promote to non-dev release. + +1.10_2 2015-01-25 + - Put the problematic test as a TODO. + +1.10_1 2015-01-22 + - Increase timeouts in test to address FreeBSD failures. + +1.09 2015-01-08 + - Test was failing on Windows platforms. (Yanick Champoux) + +1.08 2015-01-07 + - New helper functions 'max_procs', 'running_procs' and + 'wait_for_available_procs'. GH#4 (Yanick Champoux) + - Play nicer with calls to 'waitpid' done outside of P::FM. GH#3 (Yanick + Champoux) + +1.07 2014-11-10 + - Increase minimal Test::Simple requirement RT #92801 + - Implement better style and practices in the examples in the POD. + (Shlomi Fish) + +1.06 2013-12-24 + - Remove temporary directory only if it was an automatically generated + one. Now fixed. (Shoichi Kaji) RT #89590 (johantheolive) + +1.05 2013-09-18 + - Remove temporary directory only if it was an automatically generated + one. (reported by Manuel Jeckelmann) + +1.04 2013-09-03 + - Require File::Path 2.0 to support Perl 5.8 (Ian Burrell) + - fix some typos #88358 (David Steinbrunner) + - documentation fixes #84337 (Damyan Ivanov) + +1.03 2013-03-06 + - Use second parameter from new() that was unused in the last few + released. (Michael Gang) + +1.02 2012-12-24 + - Fix test for Windows. + +1.01 2012-12-23 + - Disable utf8 test on Windows where it is a perl bug. + - Change version number scheme to two parts. + +1.0.0 2012-12-23 + - Fixing RT 68298 - Insecure /tmp file handling using File::Temp::tempdir + by John Lightsey (LIGHTSEY) + - Adding another callback example and several tests Gabor Szabo (SZABGAB) + +0.7 2001-04-04 + - callback code tested, exit status return (Chuck, dLux) + - added parallel_get.pl, a parallel webget example (dLux) + - added callbacks.pl, a callback example (Chuck, dLux) + - documentation updtes (Chuck, dLux) + +0.6 2000-11-30 + - documentation tweak fixes by Noah Robin + - warning elimination fixes + +0.5 2000-10-18 + - original version; created by h2xs 1.19 + +0.7.9 2010-11-01 + - Exclude the example scripts from getting installed. + (https://rt.cpan.org/Public/Bug/Display.html?id=62506) + +0.7.8 2010-08-25 + - Make $VERSION compatible with the most perl versions possible + (http://rt.cpan.org/Public/Bug/Display.html?id=62180) + +0.7.7 2010-09-28 + - Small distribution fixes + +0.7.6 2010-08-15 + - Added datastructure retrieval (Ken Clarke) + - Using CORE::exit instead of exit + (http://rt.cpan.org/Public/Bug/Display.html?id=39003) + +0.7.5 2002-12-25 + - Documentation fixes + - Fix bug if you specify max_procs = 0 + +0.7.4 2002-07-04 + - on_wait callback now runs from the wait_all_children method + - run_on_wait can run a task periodically, not only once. + +0.7.3 2001-08-24 + - minor bugfix on calling the "on_finish" callback + +0.7.2 2001-05-14 + - win32 port + - fix for the broken wait_one_child + +0.7.1 2001-04-26 + - various semantical and grammar fixes in the documentation + - on_finish now get the exit signal also + - on_start now get the process-identification also + - described limitations in the doc diff --git a/Parallel-ForkManager-1.17/INSTALL b/Parallel-ForkManager-1.17/INSTALL new file mode 100644 index 0000000..af77424 --- /dev/null +++ b/Parallel-ForkManager-1.17/INSTALL @@ -0,0 +1,43 @@ +This is the Perl distribution Parallel-ForkManager. + +Installing Parallel-ForkManager is straightforward. + +## Installation with cpanm + +If you have cpanm, you only need one line: + + % cpanm Parallel::ForkManager + +If you are installing into a system-wide directory, you may need to pass the +"-S" flag to cpanm, which uses sudo to install the module: + + % cpanm -S Parallel::ForkManager + +## Installing with the CPAN shell + +Alternatively, if your CPAN shell is set up, you should just be able to do: + + % cpan Parallel::ForkManager + +## Manual installation + +As a last resort, you can manually install it. Download the tarball, untar it, +then build it: + + % perl Makefile.PL + % make && make test + +Then install it: + + % make install + +If you are installing into a system-wide directory, you may need to run: + + % sudo make install + +## Documentation + +Parallel-ForkManager documentation is available as POD. +You can run perldoc from a shell to read the documentation: + + % perldoc Parallel::ForkManager diff --git a/Parallel-ForkManager-1.17/MANIFEST b/Parallel-ForkManager-1.17/MANIFEST new file mode 100644 index 0000000..ca8628a --- /dev/null +++ b/Parallel-ForkManager-1.17/MANIFEST @@ -0,0 +1,30 @@ +CONTRIBUTORS +Changes +INSTALL +MANIFEST +META.json +META.yml +Makefile.PL +README.mkdn +SIGNATURE +cpanfile +doap.xml +examples/callback.pl +examples/callback_data.pl +examples/parallel_get.pl +lib/Parallel/ForkManager.pm +t/00-compile.t +t/00-load.t +t/00-report-prereqs.dd +t/00-report-prereqs.t +t/01-utf8-all.t +t/02-callback.t +t/03-callback-data.t +t/basic-methods.t +t/callback.txt +t/callback_data.txt +t/waitpid-conflict.t +t/waitpid-waitonechild.t +t/waitpid_blocking.t +xt/release/pause-permissions.t +xt/release/unused-vars.t diff --git a/Parallel-ForkManager-1.17/META.json b/Parallel-ForkManager-1.17/META.json new file mode 100644 index 0000000..63f17ab --- /dev/null +++ b/Parallel-ForkManager-1.17/META.json @@ -0,0 +1,84 @@ +{ + "abstract" : "A simple parallel processing fork manager", + "author" : [ + "dLux (Szabó, Balázs) ", + "Yanick Champoux ", + "Gabor Szabo " + ], + "dynamic_config" : 0, + "generated_by" : "Dist::Zilla version 5.040, CPAN::Meta::Converter version 2.150001", + "license" : [ + "perl_5" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "Parallel-ForkManager", + "prereqs" : { + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + }, + "develop" : { + "requires" : { + "Test::More" : "0.96", + "Test::PAUSE::Permissions" : "0", + "Test::Vars" : "0", + "warnings" : "0" + } + }, + "runtime" : { + "requires" : { + "Carp" : "0", + "File::Path" : "0", + "File::Spec" : "0", + "File::Temp" : "0", + "POSIX" : "0", + "Storable" : "0", + "strict" : "0" + } + }, + "test" : { + "recommends" : { + "CPAN::Meta" : "2.120900" + }, + "requires" : { + "ExtUtils::MakeMaker" : "0", + "File::Spec" : "0", + "IO::Handle" : "0", + "IPC::Open3" : "0", + "Test::More" : "0.94", + "Test::Warn" : "0", + "perl" : "5.006", + "warnings" : "0" + } + } + }, + "provides" : { + "Parallel::ForkManager" : { + "file" : "lib/Parallel/ForkManager.pm", + "version" : "1.17" + } + }, + "release_status" : "stable", + "resources" : { + "bugtracker" : { + "web" : "https://github.com/dluxhu/perl-parallel-forkmanager/issues" + }, + "homepage" : "https://github.com/dluxhu/perl-parallel-forkmanager", + "repository" : { + "type" : "git", + "url" : "https://github.com/dluxhu/perl-parallel-forkmanager.git", + "web" : "https://github.com/dluxhu/perl-parallel-forkmanager" + } + }, + "version" : "1.17", + "x_authority" : "cpan:DLUX", + "x_contributors" : [ + "Ninebit ", + "Shlomi Fish " + ] +} + diff --git a/Parallel-ForkManager-1.17/META.yml b/Parallel-ForkManager-1.17/META.yml new file mode 100644 index 0000000..ef5cb2e --- /dev/null +++ b/Parallel-ForkManager-1.17/META.yml @@ -0,0 +1,45 @@ +--- +abstract: 'A simple parallel processing fork manager' +author: + - 'dLux (Szabó, Balázs) ' + - 'Yanick Champoux ' + - 'Gabor Szabo ' +build_requires: + ExtUtils::MakeMaker: '0' + File::Spec: '0' + IO::Handle: '0' + IPC::Open3: '0' + Test::More: '0.94' + Test::Warn: '0' + perl: '5.006' + warnings: '0' +configure_requires: + ExtUtils::MakeMaker: '0' +dynamic_config: 0 +generated_by: 'Dist::Zilla version 5.040, CPAN::Meta::Converter version 2.150001' +license: perl +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: '1.4' +name: Parallel-ForkManager +provides: + Parallel::ForkManager: + file: lib/Parallel/ForkManager.pm + version: '1.17' +requires: + Carp: '0' + File::Path: '0' + File::Spec: '0' + File::Temp: '0' + POSIX: '0' + Storable: '0' + strict: '0' +resources: + bugtracker: https://github.com/dluxhu/perl-parallel-forkmanager/issues + homepage: https://github.com/dluxhu/perl-parallel-forkmanager + repository: https://github.com/dluxhu/perl-parallel-forkmanager.git +version: '1.17' +x_authority: cpan:DLUX +x_contributors: + - 'Ninebit ' + - 'Shlomi Fish ' diff --git a/Parallel-ForkManager-1.17/MYMETA.json b/Parallel-ForkManager-1.17/MYMETA.json new file mode 100644 index 0000000..f0421ad --- /dev/null +++ b/Parallel-ForkManager-1.17/MYMETA.json @@ -0,0 +1,88 @@ +{ + "abstract" : "A simple parallel processing fork manager", + "author" : [ + "dLux (Szabó, Balázs) ", + "Yanick Champoux ", + "Gabor Szabo " + ], + "dynamic_config" : 0, + "generated_by" : "Dist::Zilla version 5.040, CPAN::Meta::Converter version 2.150001, CPAN::Meta::Converter version 2.120921", + "license" : [ + "perl_5" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "Parallel-ForkManager", + "prereqs" : { + "build" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + }, + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "0" + } + }, + "develop" : { + "requires" : { + "Test::More" : "0.96", + "Test::PAUSE::Permissions" : "0", + "Test::Vars" : "0", + "warnings" : "0" + } + }, + "runtime" : { + "requires" : { + "Carp" : "0", + "File::Path" : "0", + "File::Spec" : "0", + "File::Temp" : "0", + "POSIX" : "0", + "Storable" : "0", + "perl" : "5.006", + "strict" : "0" + } + }, + "test" : { + "recommends" : { + "CPAN::Meta" : "2.120900" + }, + "requires" : { + "ExtUtils::MakeMaker" : "0", + "File::Spec" : "0", + "IO::Handle" : "0", + "IPC::Open3" : "0", + "Test::More" : "0.94", + "Test::Warn" : "0", + "warnings" : "0" + } + } + }, + "provides" : { + "Parallel::ForkManager" : { + "file" : "lib/Parallel/ForkManager.pm", + "version" : "1.17" + } + }, + "release_status" : "stable", + "resources" : { + "bugtracker" : { + "web" : "https://github.com/dluxhu/perl-parallel-forkmanager/issues" + }, + "homepage" : "https://github.com/dluxhu/perl-parallel-forkmanager", + "repository" : { + "type" : "git", + "url" : "https://github.com/dluxhu/perl-parallel-forkmanager.git", + "web" : "https://github.com/dluxhu/perl-parallel-forkmanager" + } + }, + "version" : "1.17", + "x_authority" : "cpan:DLUX", + "x_contributors" : [ + "Ninebit ", + "Shlomi Fish " + ] +} diff --git a/Parallel-ForkManager-1.17/MYMETA.yml b/Parallel-ForkManager-1.17/MYMETA.yml new file mode 100644 index 0000000..43f7e33 --- /dev/null +++ b/Parallel-ForkManager-1.17/MYMETA.yml @@ -0,0 +1,45 @@ +--- +abstract: 'A simple parallel processing fork manager' +author: + - 'dLux (Szabó, Balázs) ' + - 'Yanick Champoux ' + - 'Gabor Szabo ' +build_requires: + ExtUtils::MakeMaker: 0 + File::Spec: 0 + IO::Handle: 0 + IPC::Open3: 0 + Test::More: 0.94 + Test::Warn: 0 + warnings: 0 +configure_requires: + ExtUtils::MakeMaker: 0 +dynamic_config: 0 +generated_by: 'Dist::Zilla version 5.040, CPAN::Meta::Converter version 2.150001, CPAN::Meta::Converter version 2.120921' +license: perl +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: 1.4 +name: Parallel-ForkManager +provides: + Parallel::ForkManager: + file: lib/Parallel/ForkManager.pm + version: 1.17 +requires: + Carp: 0 + File::Path: 0 + File::Spec: 0 + File::Temp: 0 + POSIX: 0 + Storable: 0 + perl: 5.006 + strict: 0 +resources: + bugtracker: https://github.com/dluxhu/perl-parallel-forkmanager/issues + homepage: https://github.com/dluxhu/perl-parallel-forkmanager + repository: https://github.com/dluxhu/perl-parallel-forkmanager.git +version: 1.17 +x_authority: cpan:DLUX +x_contributors: + - 'Ninebit ' + - 'Shlomi Fish ' diff --git a/Parallel-ForkManager-1.17/Makefile b/Parallel-ForkManager-1.17/Makefile new file mode 100644 index 0000000..f8fa563 --- /dev/null +++ b/Parallel-ForkManager-1.17/Makefile @@ -0,0 +1,877 @@ +# This Makefile is for the Parallel::ForkManager extension to perl. +# +# It was generated automatically by MakeMaker version +# 6.66 (Revision: 66600) from the contents of +# Makefile.PL. Don't edit this file, edit Makefile.PL instead. +# +# ANY CHANGES MADE HERE WILL BE LOST! +# +# MakeMaker ARGV: () +# + +# MakeMaker Parameters: + +# ABSTRACT => q[A simple parallel processing fork manager] +# AUTHOR => [q[dLux (Szabó, Balázs) , Yanick Champoux , Gabor Szabo ]] +# BUILD_REQUIRES => { } +# CONFIGURE_REQUIRES => { ExtUtils::MakeMaker=>q[0] } +# DISTNAME => q[Parallel-ForkManager] +# LICENSE => q[perl] +# MIN_PERL_VERSION => q[5.006] +# NAME => q[Parallel::ForkManager] +# PREREQ_PM => { Test::More=>q[0.94], File::Spec=>q[0], File::Path=>q[0], IO::Handle=>q[0], ExtUtils::MakeMaker=>q[0], POSIX=>q[0], warnings=>q[0], IPC::Open3=>q[0], strict=>q[0], Test::Warn=>q[0], Storable=>q[0], File::Temp=>q[0], Carp=>q[0] } +# TEST_REQUIRES => { ExtUtils::MakeMaker=>q[0], IO::Handle=>q[0], File::Spec=>q[0], Test::Warn=>q[0], Test::More=>q[0.94], IPC::Open3=>q[0], warnings=>q[0] } +# VERSION => q[1.17] +# test => { TESTS=>q[t/*.t] } + +# --- MakeMaker post_initialize section: + + +# --- MakeMaker const_config section: + +# These definitions are from config.sh (via /usr/lib/perl/5.18/Config.pm). +# They may have been overridden via Makefile.PL or on the command line. +AR = ar +CC = cc +CCCDLFLAGS = -fPIC +CCDLFLAGS = -Wl,-E +DLEXT = so +DLSRC = dl_dlopen.xs +EXE_EXT = +FULL_AR = /usr/bin/ar +LD = cc +LDDLFLAGS = -shared -L/usr/local/lib -fstack-protector +LDFLAGS = -fstack-protector -L/usr/local/lib +LIBC = +LIB_EXT = .a +OBJ_EXT = .o +OSNAME = linux +OSVERS = 3.2.0-58-generic +RANLIB = : +SITELIBEXP = /usr/local/share/perl/5.18.2 +SITEARCHEXP = /usr/local/lib/perl/5.18.2 +SO = so +VENDORARCHEXP = /usr/lib/perl5 +VENDORLIBEXP = /usr/share/perl5 + + +# --- MakeMaker constants section: +AR_STATIC_ARGS = cr +DIRFILESEP = / +DFSEP = $(DIRFILESEP) +NAME = Parallel::ForkManager +NAME_SYM = Parallel_ForkManager +VERSION = 1.17 +VERSION_MACRO = VERSION +VERSION_SYM = 1_17 +DEFINE_VERSION = -D$(VERSION_MACRO)=\"$(VERSION)\" +XS_VERSION = 1.17 +XS_VERSION_MACRO = XS_VERSION +XS_DEFINE_VERSION = -D$(XS_VERSION_MACRO)=\"$(XS_VERSION)\" +INST_ARCHLIB = blib/arch +INST_SCRIPT = blib/script +INST_BIN = blib/bin +INST_LIB = blib/lib +INST_MAN1DIR = blib/man1 +INST_MAN3DIR = blib/man3 +MAN1EXT = 1p +MAN3EXT = 3pm +INSTALLDIRS = site +DESTDIR = +PREFIX = /usr +PERLPREFIX = $(PREFIX) +SITEPREFIX = $(PREFIX)/local +VENDORPREFIX = $(PREFIX) +INSTALLPRIVLIB = $(PERLPREFIX)/share/perl/5.18 +DESTINSTALLPRIVLIB = $(DESTDIR)$(INSTALLPRIVLIB) +INSTALLSITELIB = $(SITEPREFIX)/share/perl/5.18.2 +DESTINSTALLSITELIB = $(DESTDIR)$(INSTALLSITELIB) +INSTALLVENDORLIB = $(VENDORPREFIX)/share/perl5 +DESTINSTALLVENDORLIB = $(DESTDIR)$(INSTALLVENDORLIB) +INSTALLARCHLIB = $(PERLPREFIX)/lib/perl/5.18 +DESTINSTALLARCHLIB = $(DESTDIR)$(INSTALLARCHLIB) +INSTALLSITEARCH = $(SITEPREFIX)/lib/perl/5.18.2 +DESTINSTALLSITEARCH = $(DESTDIR)$(INSTALLSITEARCH) +INSTALLVENDORARCH = $(VENDORPREFIX)/lib/perl5 +DESTINSTALLVENDORARCH = $(DESTDIR)$(INSTALLVENDORARCH) +INSTALLBIN = $(PERLPREFIX)/bin +DESTINSTALLBIN = $(DESTDIR)$(INSTALLBIN) +INSTALLSITEBIN = $(SITEPREFIX)/bin +DESTINSTALLSITEBIN = $(DESTDIR)$(INSTALLSITEBIN) +INSTALLVENDORBIN = $(VENDORPREFIX)/bin +DESTINSTALLVENDORBIN = $(DESTDIR)$(INSTALLVENDORBIN) +INSTALLSCRIPT = $(PERLPREFIX)/bin +DESTINSTALLSCRIPT = $(DESTDIR)$(INSTALLSCRIPT) +INSTALLSITESCRIPT = $(SITEPREFIX)/bin +DESTINSTALLSITESCRIPT = $(DESTDIR)$(INSTALLSITESCRIPT) +INSTALLVENDORSCRIPT = $(VENDORPREFIX)/bin +DESTINSTALLVENDORSCRIPT = $(DESTDIR)$(INSTALLVENDORSCRIPT) +INSTALLMAN1DIR = $(PERLPREFIX)/share/man/man1 +DESTINSTALLMAN1DIR = $(DESTDIR)$(INSTALLMAN1DIR) +INSTALLSITEMAN1DIR = $(SITEPREFIX)/man/man1 +DESTINSTALLSITEMAN1DIR = $(DESTDIR)$(INSTALLSITEMAN1DIR) +INSTALLVENDORMAN1DIR = $(VENDORPREFIX)/share/man/man1 +DESTINSTALLVENDORMAN1DIR = $(DESTDIR)$(INSTALLVENDORMAN1DIR) +INSTALLMAN3DIR = $(PERLPREFIX)/share/man/man3 +DESTINSTALLMAN3DIR = $(DESTDIR)$(INSTALLMAN3DIR) +INSTALLSITEMAN3DIR = $(SITEPREFIX)/man/man3 +DESTINSTALLSITEMAN3DIR = $(DESTDIR)$(INSTALLSITEMAN3DIR) +INSTALLVENDORMAN3DIR = $(VENDORPREFIX)/share/man/man3 +DESTINSTALLVENDORMAN3DIR = $(DESTDIR)$(INSTALLVENDORMAN3DIR) +PERL_LIB = /usr/share/perl/5.18 +PERL_ARCHLIB = /usr/lib/perl/5.18 +LIBPERL_A = libperl.a +FIRST_MAKEFILE = Makefile +MAKEFILE_OLD = Makefile.old +MAKE_APERL_FILE = Makefile.aperl +PERLMAINCC = $(CC) +PERL_INC = /usr/lib/perl/5.18/CORE +PERL = /usr/bin/perl +FULLPERL = /usr/bin/perl +ABSPERL = $(PERL) +PERLRUN = $(PERL) +FULLPERLRUN = $(FULLPERL) +ABSPERLRUN = $(ABSPERL) +PERLRUNINST = $(PERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" +FULLPERLRUNINST = $(FULLPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" +ABSPERLRUNINST = $(ABSPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" +PERL_CORE = 0 +PERM_DIR = 755 +PERM_RW = 644 +PERM_RWX = 755 + +MAKEMAKER = /usr/share/perl/5.18/ExtUtils/MakeMaker.pm +MM_VERSION = 6.66 +MM_REVISION = 66600 + +# FULLEXT = Pathname for extension directory (eg Foo/Bar/Oracle). +# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT. (eg Oracle) +# PARENT_NAME = NAME without BASEEXT and no trailing :: (eg Foo::Bar) +# DLBASE = Basename part of dynamic library. May be just equal BASEEXT. +MAKE = make +FULLEXT = Parallel/ForkManager +BASEEXT = ForkManager +PARENT_NAME = Parallel +DLBASE = $(BASEEXT) +VERSION_FROM = +OBJECT = +LDFROM = $(OBJECT) +LINKTYPE = dynamic +BOOTDEP = + +# Handy lists of source code files: +XS_FILES = +C_FILES = +O_FILES = +H_FILES = +MAN1PODS = +MAN3PODS = lib/Parallel/ForkManager.pm + +# Where is the Config information that we are using/depend on +CONFIGDEP = $(PERL_ARCHLIB)$(DFSEP)Config.pm $(PERL_INC)$(DFSEP)config.h + +# Where to build things +INST_LIBDIR = $(INST_LIB)/Parallel +INST_ARCHLIBDIR = $(INST_ARCHLIB)/Parallel + +INST_AUTODIR = $(INST_LIB)/auto/$(FULLEXT) +INST_ARCHAUTODIR = $(INST_ARCHLIB)/auto/$(FULLEXT) + +INST_STATIC = +INST_DYNAMIC = +INST_BOOT = + +# Extra linker info +EXPORT_LIST = +PERL_ARCHIVE = +PERL_ARCHIVE_AFTER = + + +TO_INST_PM = lib/Parallel/ForkManager.pm + +PM_TO_BLIB = lib/Parallel/ForkManager.pm \ + blib/lib/Parallel/ForkManager.pm + + +# --- MakeMaker platform_constants section: +MM_Unix_VERSION = 6.66 +PERL_MALLOC_DEF = -DPERL_EXTMALLOC_DEF -Dmalloc=Perl_malloc -Dfree=Perl_mfree -Drealloc=Perl_realloc -Dcalloc=Perl_calloc + + +# --- MakeMaker tool_autosplit section: +# Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto +AUTOSPLITFILE = $(ABSPERLRUN) -e 'use AutoSplit; autosplit($$$$ARGV[0], $$$$ARGV[1], 0, 1, 1)' -- + + + +# --- MakeMaker tool_xsubpp section: + + +# --- MakeMaker tools_other section: +SHELL = /bin/sh +CHMOD = chmod +CP = cp +MV = mv +NOOP = $(TRUE) +NOECHO = @ +RM_F = rm -f +RM_RF = rm -rf +TEST_F = test -f +TOUCH = touch +UMASK_NULL = umask 0 +DEV_NULL = > /dev/null 2>&1 +MKPATH = $(ABSPERLRUN) -MExtUtils::Command -e 'mkpath' -- +EQUALIZE_TIMESTAMP = $(ABSPERLRUN) -MExtUtils::Command -e 'eqtime' -- +FALSE = false +TRUE = true +ECHO = echo +ECHO_N = echo -n +UNINST = 0 +VERBINST = 0 +MOD_INSTALL = $(ABSPERLRUN) -MExtUtils::Install -e 'install([ from_to => {@ARGV}, verbose => '\''$(VERBINST)'\'', uninstall_shadows => '\''$(UNINST)'\'', dir_mode => '\''$(PERM_DIR)'\'' ]);' -- +DOC_INSTALL = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'perllocal_install' -- +UNINSTALL = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'uninstall' -- +WARN_IF_OLD_PACKLIST = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'warn_if_old_packlist' -- +MACROSTART = +MACROEND = +USEMAKEFILE = -f +FIXIN = $(ABSPERLRUN) -MExtUtils::MY -e 'MY->fixin(shift)' -- + + +# --- MakeMaker makemakerdflt section: +makemakerdflt : all + $(NOECHO) $(NOOP) + + +# --- MakeMaker dist section: +TAR = tar +TARFLAGS = cvf +ZIP = zip +ZIPFLAGS = -r +COMPRESS = gzip --best +SUFFIX = .gz +SHAR = shar +PREOP = $(NOECHO) $(NOOP) +POSTOP = $(NOECHO) $(NOOP) +TO_UNIX = $(NOECHO) $(NOOP) +CI = ci -u +RCS_LABEL = rcs -Nv$(VERSION_SYM): -q +DIST_CP = best +DIST_DEFAULT = tardist +DISTNAME = Parallel-ForkManager +DISTVNAME = Parallel-ForkManager-1.17 + + +# --- MakeMaker macro section: + + +# --- MakeMaker depend section: + + +# --- MakeMaker cflags section: + + +# --- MakeMaker const_loadlibs section: + + +# --- MakeMaker const_cccmd section: + + +# --- MakeMaker post_constants section: + + +# --- MakeMaker pasthru section: + +PASTHRU = LIBPERL_A="$(LIBPERL_A)"\ + LINKTYPE="$(LINKTYPE)"\ + LD="$(LD)"\ + PREFIX="$(PREFIX)" + + +# --- MakeMaker special_targets section: +.SUFFIXES : .xs .c .C .cpp .i .s .cxx .cc $(OBJ_EXT) + +.PHONY: all config static dynamic test linkext manifest blibdirs clean realclean disttest distdir + + + +# --- MakeMaker c_o section: + + +# --- MakeMaker xs_c section: + + +# --- MakeMaker xs_o section: + + +# --- MakeMaker top_targets section: +all :: pure_all manifypods + $(NOECHO) $(NOOP) + + +pure_all :: config pm_to_blib subdirs linkext + $(NOECHO) $(NOOP) + +subdirs :: $(MYEXTLIB) + $(NOECHO) $(NOOP) + +config :: $(FIRST_MAKEFILE) blibdirs + $(NOECHO) $(NOOP) + +help : + perldoc ExtUtils::MakeMaker + + +# --- MakeMaker blibdirs section: +blibdirs : $(INST_LIBDIR)$(DFSEP).exists $(INST_ARCHLIB)$(DFSEP).exists $(INST_AUTODIR)$(DFSEP).exists $(INST_ARCHAUTODIR)$(DFSEP).exists $(INST_BIN)$(DFSEP).exists $(INST_SCRIPT)$(DFSEP).exists $(INST_MAN1DIR)$(DFSEP).exists $(INST_MAN3DIR)$(DFSEP).exists + $(NOECHO) $(NOOP) + +# Backwards compat with 6.18 through 6.25 +blibdirs.ts : blibdirs + $(NOECHO) $(NOOP) + +$(INST_LIBDIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_LIBDIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_LIBDIR) + $(NOECHO) $(TOUCH) $(INST_LIBDIR)$(DFSEP).exists + +$(INST_ARCHLIB)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_ARCHLIB) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_ARCHLIB) + $(NOECHO) $(TOUCH) $(INST_ARCHLIB)$(DFSEP).exists + +$(INST_AUTODIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_AUTODIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_AUTODIR) + $(NOECHO) $(TOUCH) $(INST_AUTODIR)$(DFSEP).exists + +$(INST_ARCHAUTODIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_ARCHAUTODIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_ARCHAUTODIR) + $(NOECHO) $(TOUCH) $(INST_ARCHAUTODIR)$(DFSEP).exists + +$(INST_BIN)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_BIN) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_BIN) + $(NOECHO) $(TOUCH) $(INST_BIN)$(DFSEP).exists + +$(INST_SCRIPT)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_SCRIPT) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_SCRIPT) + $(NOECHO) $(TOUCH) $(INST_SCRIPT)$(DFSEP).exists + +$(INST_MAN1DIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_MAN1DIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_MAN1DIR) + $(NOECHO) $(TOUCH) $(INST_MAN1DIR)$(DFSEP).exists + +$(INST_MAN3DIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_MAN3DIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_MAN3DIR) + $(NOECHO) $(TOUCH) $(INST_MAN3DIR)$(DFSEP).exists + + + +# --- MakeMaker linkext section: + +linkext :: $(LINKTYPE) + $(NOECHO) $(NOOP) + + +# --- MakeMaker dlsyms section: + + +# --- MakeMaker dynamic section: + +dynamic :: $(FIRST_MAKEFILE) $(INST_DYNAMIC) $(INST_BOOT) + $(NOECHO) $(NOOP) + + +# --- MakeMaker dynamic_bs section: + +BOOTSTRAP = + + +# --- MakeMaker dynamic_lib section: + + +# --- MakeMaker static section: + +## $(INST_PM) has been moved to the all: target. +## It remains here for awhile to allow for old usage: "make static" +static :: $(FIRST_MAKEFILE) $(INST_STATIC) + $(NOECHO) $(NOOP) + + +# --- MakeMaker static_lib section: + + +# --- MakeMaker manifypods section: + +POD2MAN_EXE = $(PERLRUN) "-MExtUtils::Command::MM" -e pod2man "--" +POD2MAN = $(POD2MAN_EXE) + + +manifypods : pure_all \ + lib/Parallel/ForkManager.pm + $(NOECHO) $(POD2MAN) --section=$(MAN3EXT) --perm_rw=$(PERM_RW) \ + lib/Parallel/ForkManager.pm $(INST_MAN3DIR)/Parallel::ForkManager.$(MAN3EXT) + + + + +# --- MakeMaker processPL section: + + +# --- MakeMaker installbin section: + + +# --- MakeMaker subdirs section: + +# none + +# --- MakeMaker clean_subdirs section: +clean_subdirs : + $(NOECHO) $(NOOP) + + +# --- MakeMaker clean section: + +# Delete temporary files but do not touch installed files. We don't delete +# the Makefile here so a later make realclean still has a makefile to use. + +clean :: clean_subdirs + - $(RM_F) \ + perlmain.c core.[0-9][0-9] \ + $(BASEEXT).bso perl.exe \ + core.[0-9] $(MAKE_APERL_FILE) \ + pm_to_blib core.[0-9][0-9][0-9][0-9][0-9] \ + $(BASEEXT).def tmon.out \ + MYMETA.yml core.[0-9][0-9][0-9] \ + $(BASEEXT).exp *$(LIB_EXT) \ + pm_to_blib.ts perl \ + *$(OBJ_EXT) lib$(BASEEXT).def \ + blibdirs.ts core.[0-9][0-9][0-9][0-9] \ + $(INST_ARCHAUTODIR)/extralibs.all MYMETA.json \ + core.*perl.*.? core \ + $(INST_ARCHAUTODIR)/extralibs.ld $(BASEEXT).x \ + mon.out *perl.core \ + $(BOOTSTRAP) so_locations \ + perl$(EXE_EXT) + - $(RM_RF) \ + blib + - $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) $(DEV_NULL) + + +# --- MakeMaker realclean_subdirs section: +realclean_subdirs : + $(NOECHO) $(NOOP) + + +# --- MakeMaker realclean section: +# Delete temporary files (via clean) and also delete dist files +realclean purge :: clean realclean_subdirs + - $(RM_F) \ + $(FIRST_MAKEFILE) $(MAKEFILE_OLD) + - $(RM_RF) \ + $(DISTVNAME) + + +# --- MakeMaker metafile section: +metafile : create_distdir + $(NOECHO) $(ECHO) Generating META.yml + $(NOECHO) $(ECHO) '---' > META_new.yml + $(NOECHO) $(ECHO) 'abstract: '\''A simple parallel processing fork manager'\''' >> META_new.yml + $(NOECHO) $(ECHO) 'author:' >> META_new.yml + $(NOECHO) $(ECHO) ' - '\''dLux (Szabó, Balázs) , Yanick Champoux , Gabor Szabo '\''' >> META_new.yml + $(NOECHO) $(ECHO) 'build_requires:' >> META_new.yml + $(NOECHO) $(ECHO) ' ExtUtils::MakeMaker: 0' >> META_new.yml + $(NOECHO) $(ECHO) ' File::Spec: 0' >> META_new.yml + $(NOECHO) $(ECHO) ' IO::Handle: 0' >> META_new.yml + $(NOECHO) $(ECHO) ' IPC::Open3: 0' >> META_new.yml + $(NOECHO) $(ECHO) ' Test::More: 0.94' >> META_new.yml + $(NOECHO) $(ECHO) ' Test::Warn: 0' >> META_new.yml + $(NOECHO) $(ECHO) ' warnings: 0' >> META_new.yml + $(NOECHO) $(ECHO) 'configure_requires:' >> META_new.yml + $(NOECHO) $(ECHO) ' ExtUtils::MakeMaker: 0' >> META_new.yml + $(NOECHO) $(ECHO) 'dynamic_config: 1' >> META_new.yml + $(NOECHO) $(ECHO) 'generated_by: '\''ExtUtils::MakeMaker version 6.66, CPAN::Meta::Converter version 2.120921'\''' >> META_new.yml + $(NOECHO) $(ECHO) 'license: perl' >> META_new.yml + $(NOECHO) $(ECHO) 'meta-spec:' >> META_new.yml + $(NOECHO) $(ECHO) ' url: http://module-build.sourceforge.net/META-spec-v1.4.html' >> META_new.yml + $(NOECHO) $(ECHO) ' version: 1.4' >> META_new.yml + $(NOECHO) $(ECHO) 'name: Parallel-ForkManager' >> META_new.yml + $(NOECHO) $(ECHO) 'no_index:' >> META_new.yml + $(NOECHO) $(ECHO) ' directory:' >> META_new.yml + $(NOECHO) $(ECHO) ' - t' >> META_new.yml + $(NOECHO) $(ECHO) ' - inc' >> META_new.yml + $(NOECHO) $(ECHO) 'requires:' >> META_new.yml + $(NOECHO) $(ECHO) ' Carp: 0' >> META_new.yml + $(NOECHO) $(ECHO) ' File::Path: 0' >> META_new.yml + $(NOECHO) $(ECHO) ' File::Spec: 0' >> META_new.yml + $(NOECHO) $(ECHO) ' File::Temp: 0' >> META_new.yml + $(NOECHO) $(ECHO) ' POSIX: 0' >> META_new.yml + $(NOECHO) $(ECHO) ' Storable: 0' >> META_new.yml + $(NOECHO) $(ECHO) ' perl: 5.006' >> META_new.yml + $(NOECHO) $(ECHO) ' strict: 0' >> META_new.yml + $(NOECHO) $(ECHO) 'version: 1.17' >> META_new.yml + -$(NOECHO) $(MV) META_new.yml $(DISTVNAME)/META.yml + $(NOECHO) $(ECHO) Generating META.json + $(NOECHO) $(ECHO) '{' > META_new.json + $(NOECHO) $(ECHO) ' "abstract" : "A simple parallel processing fork manager",' >> META_new.json + $(NOECHO) $(ECHO) ' "author" : [' >> META_new.json + $(NOECHO) $(ECHO) ' "dLux (Szabó, Balázs) , Yanick Champoux , Gabor Szabo "' >> META_new.json + $(NOECHO) $(ECHO) ' ],' >> META_new.json + $(NOECHO) $(ECHO) ' "dynamic_config" : 1,' >> META_new.json + $(NOECHO) $(ECHO) ' "generated_by" : "ExtUtils::MakeMaker version 6.66, CPAN::Meta::Converter version 2.120921",' >> META_new.json + $(NOECHO) $(ECHO) ' "license" : [' >> META_new.json + $(NOECHO) $(ECHO) ' "perl_5"' >> META_new.json + $(NOECHO) $(ECHO) ' ],' >> META_new.json + $(NOECHO) $(ECHO) ' "meta-spec" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",' >> META_new.json + $(NOECHO) $(ECHO) ' "version" : "2"' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "name" : "Parallel-ForkManager",' >> META_new.json + $(NOECHO) $(ECHO) ' "no_index" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "directory" : [' >> META_new.json + $(NOECHO) $(ECHO) ' "t",' >> META_new.json + $(NOECHO) $(ECHO) ' "inc"' >> META_new.json + $(NOECHO) $(ECHO) ' ]' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "prereqs" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "build" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "ExtUtils::MakeMaker" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "File::Spec" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "IO::Handle" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "IPC::Open3" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "Test::More" : "0.94",' >> META_new.json + $(NOECHO) $(ECHO) ' "Test::Warn" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "warnings" : "0"' >> META_new.json + $(NOECHO) $(ECHO) ' }' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "configure" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "ExtUtils::MakeMaker" : "0"' >> META_new.json + $(NOECHO) $(ECHO) ' }' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "runtime" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "requires" : {' >> META_new.json + $(NOECHO) $(ECHO) ' "Carp" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "File::Path" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "File::Spec" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "File::Temp" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "POSIX" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "Storable" : "0",' >> META_new.json + $(NOECHO) $(ECHO) ' "perl" : "5.006",' >> META_new.json + $(NOECHO) $(ECHO) ' "strict" : "0"' >> META_new.json + $(NOECHO) $(ECHO) ' }' >> META_new.json + $(NOECHO) $(ECHO) ' }' >> META_new.json + $(NOECHO) $(ECHO) ' },' >> META_new.json + $(NOECHO) $(ECHO) ' "release_status" : "stable",' >> META_new.json + $(NOECHO) $(ECHO) ' "version" : "1.17"' >> META_new.json + $(NOECHO) $(ECHO) '}' >> META_new.json + -$(NOECHO) $(MV) META_new.json $(DISTVNAME)/META.json + + +# --- MakeMaker signature section: +signature : + cpansign -s + + +# --- MakeMaker dist_basics section: +distclean :: realclean distcheck + $(NOECHO) $(NOOP) + +distcheck : + $(PERLRUN) "-MExtUtils::Manifest=fullcheck" -e fullcheck + +skipcheck : + $(PERLRUN) "-MExtUtils::Manifest=skipcheck" -e skipcheck + +manifest : + $(PERLRUN) "-MExtUtils::Manifest=mkmanifest" -e mkmanifest + +veryclean : realclean + $(RM_F) *~ */*~ *.orig */*.orig *.bak */*.bak *.old */*.old + + + +# --- MakeMaker dist_core section: + +dist : $(DIST_DEFAULT) $(FIRST_MAKEFILE) + $(NOECHO) $(ABSPERLRUN) -l -e 'print '\''Warning: Makefile possibly out of date with $(VERSION_FROM)'\''' \ + -e ' if -e '\''$(VERSION_FROM)'\'' and -M '\''$(VERSION_FROM)'\'' < -M '\''$(FIRST_MAKEFILE)'\'';' -- + +tardist : $(DISTVNAME).tar$(SUFFIX) + $(NOECHO) $(NOOP) + +uutardist : $(DISTVNAME).tar$(SUFFIX) + uuencode $(DISTVNAME).tar$(SUFFIX) $(DISTVNAME).tar$(SUFFIX) > $(DISTVNAME).tar$(SUFFIX)_uu + +$(DISTVNAME).tar$(SUFFIX) : distdir + $(PREOP) + $(TO_UNIX) + $(TAR) $(TARFLAGS) $(DISTVNAME).tar $(DISTVNAME) + $(RM_RF) $(DISTVNAME) + $(COMPRESS) $(DISTVNAME).tar + $(POSTOP) + +zipdist : $(DISTVNAME).zip + $(NOECHO) $(NOOP) + +$(DISTVNAME).zip : distdir + $(PREOP) + $(ZIP) $(ZIPFLAGS) $(DISTVNAME).zip $(DISTVNAME) + $(RM_RF) $(DISTVNAME) + $(POSTOP) + +shdist : distdir + $(PREOP) + $(SHAR) $(DISTVNAME) > $(DISTVNAME).shar + $(RM_RF) $(DISTVNAME) + $(POSTOP) + + +# --- MakeMaker distdir section: +create_distdir : + $(RM_RF) $(DISTVNAME) + $(PERLRUN) "-MExtUtils::Manifest=manicopy,maniread" \ + -e "manicopy(maniread(),'$(DISTVNAME)', '$(DIST_CP)');" + +distdir : create_distdir distmeta + $(NOECHO) $(NOOP) + + + +# --- MakeMaker dist_test section: +disttest : distdir + cd $(DISTVNAME) && $(ABSPERLRUN) Makefile.PL + cd $(DISTVNAME) && $(MAKE) $(PASTHRU) + cd $(DISTVNAME) && $(MAKE) test $(PASTHRU) + + + +# --- MakeMaker dist_ci section: + +ci : + $(PERLRUN) "-MExtUtils::Manifest=maniread" \ + -e "@all = keys %{ maniread() };" \ + -e "print(qq{Executing $(CI) @all\n}); system(qq{$(CI) @all});" \ + -e "print(qq{Executing $(RCS_LABEL) ...\n}); system(qq{$(RCS_LABEL) @all});" + + +# --- MakeMaker distmeta section: +distmeta : create_distdir metafile + $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'exit unless -e q{META.yml};' \ + -e 'eval { maniadd({q{META.yml} => q{Module YAML meta-data (added by MakeMaker)}}) }' \ + -e ' or print "Could not add META.yml to MANIFEST: $$$${'\''@'\''}\n"' -- + $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'exit unless -f q{META.json};' \ + -e 'eval { maniadd({q{META.json} => q{Module JSON meta-data (added by MakeMaker)}}) }' \ + -e ' or print "Could not add META.json to MANIFEST: $$$${'\''@'\''}\n"' -- + + + +# --- MakeMaker distsignature section: +distsignature : create_distdir + $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'eval { maniadd({q{SIGNATURE} => q{Public-key signature (added by MakeMaker)}}) } ' \ + -e ' or print "Could not add SIGNATURE to MANIFEST: $$$${'\''@'\''}\n"' -- + $(NOECHO) cd $(DISTVNAME) && $(TOUCH) SIGNATURE + cd $(DISTVNAME) && cpansign -s + + + +# --- MakeMaker install section: + +install :: pure_install doc_install + $(NOECHO) $(NOOP) + +install_perl :: pure_perl_install doc_perl_install + $(NOECHO) $(NOOP) + +install_site :: pure_site_install doc_site_install + $(NOECHO) $(NOOP) + +install_vendor :: pure_vendor_install doc_vendor_install + $(NOECHO) $(NOOP) + +pure_install :: pure_$(INSTALLDIRS)_install + $(NOECHO) $(NOOP) + +doc_install :: doc_$(INSTALLDIRS)_install + $(NOECHO) $(NOOP) + +pure__install : pure_site_install + $(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site + +doc__install : doc_site_install + $(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site + +pure_perl_install :: all + $(NOECHO) umask 022; $(MOD_INSTALL) \ + $(INST_LIB) $(DESTINSTALLPRIVLIB) \ + $(INST_ARCHLIB) $(DESTINSTALLARCHLIB) \ + $(INST_BIN) $(DESTINSTALLBIN) \ + $(INST_SCRIPT) $(DESTINSTALLSCRIPT) \ + $(INST_MAN1DIR) $(DESTINSTALLMAN1DIR) \ + $(INST_MAN3DIR) $(DESTINSTALLMAN3DIR) + $(NOECHO) $(WARN_IF_OLD_PACKLIST) \ + $(SITEARCHEXP)/auto/$(FULLEXT) + + +pure_site_install :: all + $(NOECHO) umask 02; $(MOD_INSTALL) \ + read $(SITEARCHEXP)/auto/$(FULLEXT)/.packlist \ + write $(DESTINSTALLSITEARCH)/auto/$(FULLEXT)/.packlist \ + $(INST_LIB) $(DESTINSTALLSITELIB) \ + $(INST_ARCHLIB) $(DESTINSTALLSITEARCH) \ + $(INST_BIN) $(DESTINSTALLSITEBIN) \ + $(INST_SCRIPT) $(DESTINSTALLSITESCRIPT) \ + $(INST_MAN1DIR) $(DESTINSTALLSITEMAN1DIR) \ + $(INST_MAN3DIR) $(DESTINSTALLSITEMAN3DIR) + $(NOECHO) $(WARN_IF_OLD_PACKLIST) \ + $(PERL_ARCHLIB)/auto/$(FULLEXT) + +pure_vendor_install :: all + $(NOECHO) umask 022; $(MOD_INSTALL) \ + $(INST_LIB) $(DESTINSTALLVENDORLIB) \ + $(INST_ARCHLIB) $(DESTINSTALLVENDORARCH) \ + $(INST_BIN) $(DESTINSTALLVENDORBIN) \ + $(INST_SCRIPT) $(DESTINSTALLVENDORSCRIPT) \ + $(INST_MAN1DIR) $(DESTINSTALLVENDORMAN1DIR) \ + $(INST_MAN3DIR) $(DESTINSTALLVENDORMAN3DIR) + +doc_perl_install :: all + +doc_site_install :: all + $(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLSITEARCH)/perllocal.pod + -$(NOECHO) umask 02; $(MKPATH) $(DESTINSTALLSITEARCH) + -$(NOECHO) umask 02; $(DOC_INSTALL) \ + "Module" "$(NAME)" \ + "installed into" "$(INSTALLSITELIB)" \ + LINKTYPE "$(LINKTYPE)" \ + VERSION "$(VERSION)" \ + EXE_FILES "$(EXE_FILES)" \ + >> $(DESTINSTALLSITEARCH)/perllocal.pod + +doc_vendor_install :: all + + +uninstall :: uninstall_from_$(INSTALLDIRS)dirs + $(NOECHO) $(NOOP) + +uninstall_from_perldirs :: + +uninstall_from_sitedirs :: + $(NOECHO) $(UNINSTALL) $(SITEARCHEXP)/auto/$(FULLEXT)/.packlist + +uninstall_from_vendordirs :: + + + +# --- MakeMaker force section: +# Phony target to force checking subdirectories. +FORCE : + $(NOECHO) $(NOOP) + + +# --- MakeMaker perldepend section: + + +# --- MakeMaker makefile section: +# We take a very conservative approach here, but it's worth it. +# We move Makefile to Makefile.old here to avoid gnu make looping. +$(FIRST_MAKEFILE) : Makefile.PL $(CONFIGDEP) + $(NOECHO) $(ECHO) "Makefile out-of-date with respect to $?" + $(NOECHO) $(ECHO) "Cleaning current config before rebuilding Makefile..." + -$(NOECHO) $(RM_F) $(MAKEFILE_OLD) + -$(NOECHO) $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) + - $(MAKE) $(USEMAKEFILE) $(MAKEFILE_OLD) clean $(DEV_NULL) + $(PERLRUN) Makefile.PL + $(NOECHO) $(ECHO) "==> Your Makefile has been rebuilt. <==" + $(NOECHO) $(ECHO) "==> Please rerun the $(MAKE) command. <==" + $(FALSE) + + + +# --- MakeMaker staticmake section: + +# --- MakeMaker makeaperl section --- +MAP_TARGET = perl +FULLPERL = /usr/bin/perl + +$(MAP_TARGET) :: static $(MAKE_APERL_FILE) + $(MAKE) $(USEMAKEFILE) $(MAKE_APERL_FILE) $@ + +$(MAKE_APERL_FILE) : $(FIRST_MAKEFILE) pm_to_blib + $(NOECHO) $(ECHO) Writing \"$(MAKE_APERL_FILE)\" for this $(MAP_TARGET) + $(NOECHO) $(PERLRUNINST) \ + Makefile.PL DIR= \ + MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \ + MAKEAPERL=1 NORECURS=1 CCCDLFLAGS= + + +# --- MakeMaker test section: + +TEST_VERBOSE=0 +TEST_TYPE=test_$(LINKTYPE) +TEST_FILE = test.pl +TEST_FILES = t/*.t +TESTDB_SW = -d + +testdb :: testdb_$(LINKTYPE) + +test :: $(TEST_TYPE) subdirs-test + +subdirs-test :: + $(NOECHO) $(NOOP) + + +test_dynamic :: pure_all + PERL_DL_NONLAZY=1 $(FULLPERLRUN) "-MExtUtils::Command::MM" "-e" "test_harness($(TEST_VERBOSE), '$(INST_LIB)', '$(INST_ARCHLIB)')" $(TEST_FILES) + +testdb_dynamic :: pure_all + PERL_DL_NONLAZY=1 $(FULLPERLRUN) $(TESTDB_SW) "-I$(INST_LIB)" "-I$(INST_ARCHLIB)" $(TEST_FILE) + +test_ : test_dynamic + +test_static :: test_dynamic +testdb_static :: testdb_dynamic + + +# --- MakeMaker ppd section: +# Creates a PPD (Perl Package Description) for a binary distribution. +ppd : + $(NOECHO) $(ECHO) '' > $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' A simple parallel processing fork manager' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' dLux (Szabó, Balázs) <dlux@dlux.hu>, Yanick Champoux <yanick@cpan.org>, Gabor Szabo <gabor@szabgab.com>' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) '' >> $(DISTNAME).ppd + + +# --- MakeMaker pm_to_blib section: + +pm_to_blib : $(FIRST_MAKEFILE) $(TO_INST_PM) + $(NOECHO) $(ABSPERLRUN) -MExtUtils::Install -e 'pm_to_blib({@ARGV}, '\''$(INST_LIB)/auto'\'', q[$(PM_FILTER)], '\''$(PERM_DIR)'\'')' -- \ + lib/Parallel/ForkManager.pm blib/lib/Parallel/ForkManager.pm + $(NOECHO) $(TOUCH) pm_to_blib + + +# --- MakeMaker selfdocument section: + + +# --- MakeMaker postamble section: + + +# End. diff --git a/Parallel-ForkManager-1.17/Makefile.PL b/Parallel-ForkManager-1.17/Makefile.PL new file mode 100644 index 0000000..49c827c --- /dev/null +++ b/Parallel-ForkManager-1.17/Makefile.PL @@ -0,0 +1,70 @@ +# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.040. +use strict; +use warnings; + +use 5.006; + +use ExtUtils::MakeMaker; + +my %WriteMakefileArgs = ( + "ABSTRACT" => "A simple parallel processing fork manager", + "AUTHOR" => "dLux (Szab\x{f3}, Bal\x{e1}zs) , Yanick Champoux , Gabor Szabo ", + "CONFIGURE_REQUIRES" => { + "ExtUtils::MakeMaker" => 0 + }, + "DISTNAME" => "Parallel-ForkManager", + "LICENSE" => "perl", + "MIN_PERL_VERSION" => "5.006", + "NAME" => "Parallel::ForkManager", + "PREREQ_PM" => { + "Carp" => 0, + "File::Path" => 0, + "File::Spec" => 0, + "File::Temp" => 0, + "POSIX" => 0, + "Storable" => 0, + "strict" => 0 + }, + "TEST_REQUIRES" => { + "ExtUtils::MakeMaker" => 0, + "File::Spec" => 0, + "IO::Handle" => 0, + "IPC::Open3" => 0, + "Test::More" => "0.94", + "Test::Warn" => 0, + "warnings" => 0 + }, + "VERSION" => "1.17", + "test" => { + "TESTS" => "t/*.t" + } +); + + +my %FallbackPrereqs = ( + "Carp" => 0, + "ExtUtils::MakeMaker" => 0, + "File::Path" => 0, + "File::Spec" => 0, + "File::Temp" => 0, + "IO::Handle" => 0, + "IPC::Open3" => 0, + "POSIX" => 0, + "Storable" => 0, + "Test::More" => "0.94", + "Test::Warn" => 0, + "strict" => 0, + "warnings" => 0 +); + + +unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { + delete $WriteMakefileArgs{TEST_REQUIRES}; + delete $WriteMakefileArgs{BUILD_REQUIRES}; + $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; +} + +delete $WriteMakefileArgs{CONFIGURE_REQUIRES} + unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; + +WriteMakefile(%WriteMakefileArgs); diff --git a/Parallel-ForkManager-1.17/README.mkdn b/Parallel-ForkManager-1.17/README.mkdn new file mode 100644 index 0000000..95320a3 --- /dev/null +++ b/Parallel-ForkManager-1.17/README.mkdn @@ -0,0 +1,537 @@ +# NAME + +Parallel::ForkManager - A simple parallel processing fork manager + +# VERSION + +version 1.17 + +# SYNOPSIS + + use Parallel::ForkManager; + + my $pm = Parallel::ForkManager->new($MAX_PROCESSES); + + DATA_LOOP: + foreach my $data (@all_data) { + # Forks and returns the pid for the child: + my $pid = $pm->start and next DATA_LOOP; + + ... do some work with $data in the child process ... + + $pm->finish; # Terminates the child process + } + +# DESCRIPTION + +This module is intended for use in operations that can be done in parallel +where the number of processes to be forked off should be limited. Typical +use is a downloader which will be retrieving hundreds/thousands of files. + +The code for a downloader would look something like this: + + use LWP::Simple; + use Parallel::ForkManager; + + ... + + my @links=( + ["http://www.foo.bar/rulez.data","rulez_data.txt"], + ["http://new.host/more_data.doc","more_data.doc"], + ... + ); + + ... + + # Max 30 processes for parallel download + my $pm = Parallel::ForkManager->new(30); + + LINKS: + foreach my $linkarray (@links) { + $pm->start and next LINKS; # do the fork + + my ($link, $fn) = @$linkarray; + warn "Cannot get $fn from $link" + if getstore($link, $fn) != RC_OK; + + $pm->finish; # do the exit in the child process + } + $pm->wait_all_children; + +First you need to instantiate the ForkManager with the "new" constructor. +You must specify the maximum number of processes to be created. If you +specify 0, then NO fork will be done; this is good for debugging purposes. + +Next, use $pm->start to do the fork. $pm returns 0 for the child process, +and child pid for the parent process (see also ["fork()" in perlfunc(1p)](http://man.he.net/man1p/perlfunc)). +The "and next" skips the internal loop in the parent process. NOTE: +$pm->start dies if the fork fails. + +$pm->finish terminates the child process (assuming a fork was done in the +"start"). + +NOTE: You cannot use $pm->start if you are already in the child process. +If you want to manage another set of subprocesses in the child process, +you must instantiate another Parallel::ForkManager object! + +# METHODS + +The comment letter indicates where the method should be run. P for parent, +C for child. + +- new $processes + + Instantiate a new Parallel::ForkManager object. You must specify the maximum + number of children to fork off. If you specify 0 (zero), then no children + will be forked. This is intended for debugging purposes. + + The optional second parameter, $tempdir, is only used if you want the + children to send back a reference to some data (see RETRIEVING DATASTRUCTURES + below). If not provided, it is set via a call to [File::Temp](https://metacpan.org/pod/File::Temp)::tempdir(). + + The new method will die if the temporary directory does not exist or it is not + a directory. + +- start \[ $process\_identifier \] + + This method does the fork. It returns the pid of the child process for + the parent, and 0 for the child process. If the $processes parameter + for the constructor is 0 then, assuming you're in the child process, + $pm->start simply returns 0. + + An optional $process\_identifier can be provided to this method... It is used by + the "run\_on\_finish" callback (see CALLBACKS) for identifying the finished + process. + +- finish \[ $exit\_code \[, $data\_structure\_reference\] \] + + Closes the child process by exiting and accepts an optional exit code + (default exit code is 0) which can be retrieved in the parent via callback. + If the second optional parameter is provided, the child attempts to send + it's contents back to the parent. If you use the program in debug mode + ($processes == 0), this method just calls the callback. + + If the $data\_structure\_reference is provided, then it is serialized and + passed to the parent process. See RETRIEVING DATASTRUCTURES for more info. + +- set\_max\_procs $processes + + Allows you to set a new maximum number of children to maintain. + +- wait\_all\_children + + You can call this method to wait for all the processes which have been + forked. This is a blocking wait. + +- reap\_finished\_children + + This is a non-blocking call to reap children and execute callbacks independent + of calls to "start" or "wait\_all\_children". Use this in scenarios where "start" + is called infrequently but you would like the callbacks executed quickly. + +- is\_parent + + Returns `true` if within the parent or `false` if within the child. + +- is\_child + + Returns `true` if within the child or `false` if within the parent. + +- max\_procs + + Returns the maximal number of processes the object will fork. + +- running\_procs + + Returns the pids of the forked processes currently monitored by the + `Parallel::ForkManager`. Note that children are still reported as running + until the fork manager harvest them, via the next call to + `start` or `wait_all_children`. + + my @pids = $pm->running_procs; + + my $nbr_children =- $pm->running_procs; + +- wait\_for\_available\_procs( $n ) + + Wait until `$n` available process slots are available. + If `$n` is not given, defaults to _1_. + +- waitpid\_blocking\_sleep + + Returns the sleep period, in seconds, of the pseudo-blocking calls. The sleep + period can be a fraction of second. + + Returns `0` if disabled. + + Defaults to 1 second. + + See _BLOCKING CALLS_ for more details. + +- set\_waitpid\_blocking\_sleep $seconds + + Sets the the sleep period, in seconds, of the pseudo-blocking calls. + Set to `0` to disable. + + See _BLOCKING CALLS_ for more details. + +# CALLBACKS + +You can define callbacks in the code, which are called on events like starting +a process or upon finish. Declare these before the first call to start(). + +The callbacks can be defined with the following methods: + +- run\_on\_finish $code \[, $pid \] + + You can define a subroutine which is called when a child is terminated. It is + called in the parent process. + + The parameters of the $code are the following: + + - pid of the process, which is terminated + - exit code of the program + - identification of the process (if provided in the "start" method) + - exit signal (0-127: signal name) + - core dump (1 if there was core dump at exit) + - datastructure reference or undef (see RETRIEVING DATASTRUCTURES) + +- run\_on\_start $code + + You can define a subroutine which is called when a child is started. It called + after the successful startup of a child in the parent process. + + The parameters of the $code are the following: + + - pid of the process which has been started + - identification of the process (if provided in the "start" method) + +- run\_on\_wait $code, \[$period\] + + You can define a subroutine which is called when the child process needs to wait + for the startup. If $period is not defined, then one call is done per + child. If $period is defined, then $code is called periodically and the + module waits for $period seconds between the two calls. Note, $period can be + fractional number also. The exact "$period seconds" is not guaranteed, + signals can shorten and the process scheduler can make it longer (on busy + systems). + + The $code called in the "start" and the "wait\_all\_children" method also. + + No parameters are passed to the $code on the call. + +# BLOCKING CALLS + +When it comes to waiting for child processes to terminate, `Parallel::ForkManager` is between +a fork and a hard place (if you excuse the terrible pun). The underlying Perl `waitpid` function +that the module relies on can block until either one specific or any child process +terminate, but not for a process part of a given group. + +This means that the module can do one of two things when it waits for +one of its child processes to terminate: + +- Only wait for its own child processes + + This is done via a loop using a `waitpid` non-blocking call and a sleep statement. + The code does something along the lines of + + while(1) { + if ( any of the P::FM child process terminated ) { + return its pid + } + + sleep $sleep_period + } + + This is the default behavior that the module will use. + This is not the most efficient way to wait for child processes, but it's + the safest way to ensure that `Parallel::ForkManager` won't interfere with + any other part of the codebase. + + The sleep period is set via the method `set_waitpid_blocking_sleep`. + +- Block until any process terminate + + Alternatively, `Parallel::ForkManager` can call `waitpid` such that it will + block until any child process terminate. If the child process was not one of + the monitored subprocesses, the wait will resume. This is more efficient, but mean + that `P::FM` can captures (and discards) the termination notification that a different + part of the code might be waiting for. + + If this is a race condition + that doesn't apply to your codebase, you can set the + _waitpid\_blocking\_sleep_ period to `0`, which will enable `waitpid` call blocking. + + my $pm = Parallel::ForkManager->new( 4 ); + + $pm->set_waitpid_blocking_sleep(0); # true blocking calls enabled + + for ( 1..100 ) { + $pm->start and next; + + ...; # do work + + $pm->finish; + } + +# RETRIEVING DATASTRUCTURES from child processes + +The ability for the parent to retrieve data structures is new as of version +0.7.6. + +Each child process may optionally send 1 data structure back to the parent. +By data structure, we mean a reference to a string, hash or array. The +contents of the data structure are written out to temporary files on disc +using the [Storable](https://metacpan.org/pod/Storable) modules' store() method. The reference is then +retrieved from within the code you send to the run\_on\_finish callback. + +The data structure can be any scalar perl data structure which makes sense: +string, numeric value or a reference to an array, hash or object. + +There are 2 steps involved in retrieving data structures: + +1) A reference to the data structure the child wishes to send back to the +parent is provided as the second argument to the finish() call. It is up +to the child to decide whether or not to send anything back to the parent. + +2) The data structure reference is retrieved using the callback provided in +the run\_on\_finish() method. + +Keep in mind that data structure retrieval is not the same as returning a +data structure from a method call. That is not what actually occurs. The +data structure referenced in a given child process is serialized and +written out to a file by [Storable](https://metacpan.org/pod/Storable). The file is subsequently read back +into memory and a new data structure belonging to the parent process is +created. Please consider the performance penality it can imply, so try to +keep the returned structure small. + +# EXAMPLES + +## Parallel get + +This small example can be used to get URLs in parallel. + + use Parallel::ForkManager; + use LWP::Simple; + + my $pm = Parallel::ForkManager->new(10); + + LINKS: + for my $link (@ARGV) { + $pm->start and next LINKS; + my ($fn) = $link =~ /^.*\/(.*?)$/; + if (!$fn) { + warn "Cannot determine filename from $fn\n"; + } else { + $0 .= " " . $fn; + print "Getting $fn from $link\n"; + my $rc = getstore($link, $fn); + print "$link downloaded. response code: $rc\n"; + }; + $pm->finish; + }; + +## Callbacks + +Example of a program using callbacks to get child exit codes: + + use strict; + use Parallel::ForkManager; + + my $max_procs = 5; + my @names = qw( Fred Jim Lily Steve Jessica Bob Dave Christine Rico Sara ); + # hash to resolve PID's back to child specific information + + my $pm = Parallel::ForkManager->new($max_procs); + + # Setup a callback for when a child finishes up so we can + # get it's exit code + $pm->run_on_finish( sub { + my ($pid, $exit_code, $ident) = @_; + print "** $ident just got out of the pool ". + "with PID $pid and exit code: $exit_code\n"; + }); + + $pm->run_on_start( sub { + my ($pid, $ident)=@_; + print "** $ident started, pid: $pid\n"; + }); + + $pm->run_on_wait( sub { + print "** Have to wait for one children ...\n" + }, + 0.5 + ); + + NAMES: + foreach my $child ( 0 .. $#names ) { + my $pid = $pm->start($names[$child]) and next NAMES; + + # This code is the child process + print "This is $names[$child], Child number $child\n"; + sleep ( 2 * $child ); + print "$names[$child], Child $child is about to get out...\n"; + sleep 1; + $pm->finish($child); # pass an exit code to finish + } + + print "Waiting for Children...\n"; + $pm->wait_all_children; + print "Everybody is out of the pool!\n"; + +## Data structure retrieval + +In this simple example, each child sends back a string reference. + + use Parallel::ForkManager 0.7.6; + use strict; + + my $pm = Parallel::ForkManager->new(2, '/server/path/to/temp/dir/'); + + # data structure retrieval and handling + $pm -> run_on_finish ( # called BEFORE the first call to start() + sub { + my ($pid, $exit_code, $ident, $exit_signal, $core_dump, $data_structure_reference) = @_; + + # retrieve data structure from child + if (defined($data_structure_reference)) { # children are not forced to send anything + my $string = ${$data_structure_reference}; # child passed a string reference + print "$string\n"; + } + else { # problems occuring during storage or retrieval will throw a warning + print qq|No message received from child process $pid!\n|; + } + } + ); + + # prep random statement components + my @foods = ('chocolate', 'ice cream', 'peanut butter', 'pickles', 'pizza', 'bacon', 'pancakes', 'spaghetti', 'cookies'); + my @preferences = ('loves', q|can't stand|, 'always wants more', 'will walk 100 miles for', 'only eats', 'would starve rather than eat'); + + # run the parallel processes + PERSONS: + foreach my $person (qw(Fred Wilma Ernie Bert Lucy Ethel Curly Moe Larry)) { + $pm->start() and next PERSONS; + + # generate a random statement about food preferences + my $statement = $person . ' ' . $preferences[int(rand @preferences)] . ' ' . $foods[int(rand @foods)]; + + # send it back to the parent process + $pm->finish(0, \$statement); # note that it's a scalar REFERENCE, not the scalar itself + } + $pm->wait_all_children; + +A second datastructure retrieval example demonstrates how children decide +whether or not to send anything back, what to send and how the parent should +process whatever is retrieved. + + use Parallel::ForkManager 0.7.6; + use Data::Dumper; # to display the data structures retrieved. + use strict; + + my $pm = Parallel::ForkManager->new(20); # using the system temp dir $L run_on_finish ( + sub { + my ($pid, $exit_code, $ident, $exit_signal, $core_dump, $data_structure_reference) = @_; + + # see what the child sent us, if anything + if (defined($data_structure_reference)) { # test rather than assume child sent anything + my $reftype = ref($data_structure_reference); + print qq|ident "$ident" returned a "$reftype" reference.\n\n|; + if (1) { # simple on/off switch to display the contents + print &Dumper($data_structure_reference) . qq|end of "$ident" sent structure\n\n|; + } + + # we can also collect retrieved data structures for processing after all children have exited + $retrieved_responses{$ident} = $data_structure_reference; + } else { + print qq|ident "$ident" did not send anything.\n\n|; + } + } + ); + + # generate a list of instructions + my @instructions = ( # a unique identifier and what the child process should send + {'name' => '%ENV keys as a string', 'send' => 'keys'}, + {'name' => 'Send Nothing'}, # not instructing the child to send anything back to the parent + {'name' => 'Childs %ENV', 'send' => 'all'}, + {'name' => 'Child chooses randomly', 'send' => 'random'}, + {'name' => 'Invalid send instructions', 'send' => 'Na Na Nana Na'}, + {'name' => 'ENV values in an array', 'send' => 'values'}, + ); + + INSTRUCTS: + foreach my $instruction (@instructions) { + $pm->start($instruction->{'name'}) and next INSTRUCTS; # this time we are using an explicit, unique child process identifier + + # last step in child processing + $pm->finish(0) unless $instruction->{'send'}; # no data structure is sent unless this child is told what to send. + + if ($instruction->{'send'} eq 'keys') { + $pm->finish(0, \join(', ', keys %ENV)); + + } elsif ($instruction->{'send'} eq 'values') { + $pm->finish(0, [values %ENV]); # kinda useless without knowing which keys they belong to... + + } elsif ($instruction->{'send'} eq 'all') { + $pm->finish(0, \%ENV); # remember, we are not "returning" anything, just copying the hash to disc + + # demonstrate clearly that the child determines what type of reference to send + } elsif ($instruction->{'send'} eq 'random') { + my $string = q|I'm just a string.|; + my @array = qw(I am an array); + my %hash = (type => 'associative array', synonym => 'hash', cool => 'very :)'); + my $return_choice = ('string', 'array', 'hash')[int(rand 3)]; # randomly choose return data type + $pm->finish(0, \$string) if ($return_choice eq 'string'); + $pm->finish(0, \@array) if ($return_choice eq 'array'); + $pm->finish(0, \%hash) if ($return_choice eq 'hash'); + + # as a responsible child, inform parent that their instruction was invalid + } else { + $pm->finish(0, \qq|Invalid instructions: "$instruction->{'send'}".|); # ordinarily I wouldn't include invalid input in a response... + } + } + $pm->wait_all_children; # blocks until all forked processes have exited + + # post fork processing of returned data structures + for (sort keys %retrieved_responses) { + print qq|Post processing "$_"...\n|; + } + +# BUGS AND LIMITATIONS + +Do not use Parallel::ForkManager in an environment, where other child +processes can affect the run of the main program, so using this module +is not recommended in an environment where fork() / wait() is already used. + +If you want to use more than one copies of the Parallel::ForkManager, then +you have to make sure that all children processes are terminated, before you +use the second object in the main program. + +You are free to use a new copy of Parallel::ForkManager in the child +processes, although I don't think it makes sense. + +# CREDITS + + Michael Gang (bug report) + Noah Robin (documentation tweaks) + Chuck Hirstius (callback exit status, example) + Grant Hopwood (win32 port) + Mark Southern (bugfix) + Ken Clarke (datastructure retrieval) + +# AUTHORS + +- dLux (Szabó, Balázs) +- Yanick Champoux [![endorse](http://api.coderwall.com/yanick/endorsecount.png)](http://coderwall.com/yanick) +- Gabor Szabo + +# COPYRIGHT AND LICENSE + +This software is copyright (c) 2000 by Balázs Szabó. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. diff --git a/Parallel-ForkManager-1.17/SIGNATURE b/Parallel-ForkManager-1.17/SIGNATURE new file mode 100644 index 0000000..23f855a --- /dev/null +++ b/Parallel-ForkManager-1.17/SIGNATURE @@ -0,0 +1,52 @@ +This file contains message digests of all files listed in MANIFEST, +signed via the Module::Signature module, version 0.79. + +To verify the content in this distribution, first make sure you have +Module::Signature installed, then type: + + % cpansign -v + +It will check each file's integrity, as well as the signature's +validity. If "==> Signature verified OK! <==" is not displayed, +the distribution may already have been compromised, and you should +not run its Makefile.PL or Build.PL. + +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +SHA1 fd95b68f03486ef0bc44ad34a47a130c661ed30e CONTRIBUTORS +SHA1 10bdcac01393e5ff3a03d245444e7cda8064811c Changes +SHA1 1fdb4343640b1dc9bf826eda0dd096ecbf52930d INSTALL +SHA1 683ab41dd12f906c6c65287ca85ce58f84f27514 MANIFEST +SHA1 f16787c18b2eb8168915e453ced37d2e6714d9da META.json +SHA1 aae8180a3fad9c7feb904e748d96c63eeceba509 META.yml +SHA1 473d501489198460965add67a59de09c83dcaf46 Makefile.PL +SHA1 cfcf94230a45c69aa9dc9a0cdf265e5056e5d39b README.mkdn +SHA1 15c889dc5dae788fc02fb6a7cc28cb9c49e4d82e cpanfile +SHA1 81dd4c98191ca1e39e8faf44f4b139f26bec51c7 doap.xml +SHA1 0bc4eff0fe3043f9fe2feb21b028780856e87203 examples/callback.pl +SHA1 1b7dab748d481089c80d416d93b96115dc4486d4 examples/callback_data.pl +SHA1 e14c174c581239b856e5b5c279716951a70f6eca examples/parallel_get.pl +SHA1 a653898f3172f90461be45ceacd440f183bacc01 lib/Parallel/ForkManager.pm +SHA1 562bfacd340b01259604e05492ef7f527d480958 t/00-compile.t +SHA1 4439fa08acd3f8cfe4658640218be5fc4ed6c260 t/00-load.t +SHA1 98b37452dda153ac3d85a6ae676ef248755d35ec t/00-report-prereqs.dd +SHA1 504a672015f8761f5bad3863d844954c9e803c3f t/00-report-prereqs.t +SHA1 4db3efffcfef330a6451166d6c7993f92bbba218 t/01-utf8-all.t +SHA1 7ff8a7ee4a5960791a23a739a43b1628279548ef t/02-callback.t +SHA1 ff8a6cea67626e7da6bf58c29c9b994d3991e4c9 t/03-callback-data.t +SHA1 19208bbd9b74cd32cbc76dcbaf67c8ca4c17e866 t/basic-methods.t +SHA1 6dce2e71e2969e784eb9a390a63b95ea05baef54 t/callback.txt +SHA1 cef973989a30e506d69e7ab93ad174fcd10a1d99 t/callback_data.txt +SHA1 e5f4aae96fc318e949d2367743e5d2ee12063246 t/waitpid-conflict.t +SHA1 a91aaaf17a7a2878a8b031d2f686dc4bebefd2e1 t/waitpid-waitonechild.t +SHA1 2fb16c9b79833c349b8429bcb047ffcbf64772a6 t/waitpid_blocking.t +SHA1 80ab1faf5d8174920b60461bf8c11e2225861f42 xt/release/pause-permissions.t +SHA1 d1fe7d94b3edc7847eb187d4ee41f66e19cf8907 xt/release/unused-vars.t +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1 + +iEYEARECAAYFAlZZvqQACgkQ34Hwf+GwC4wGMQCeNA0khEzl75EWPdR0hGyVgD42 +9I0AnA+fAUxua4DwI31mS6j9Sz0XJAHV +=RGGU +-----END PGP SIGNATURE----- diff --git a/Parallel-ForkManager-1.17/blib/arch/.exists b/Parallel-ForkManager-1.17/blib/arch/.exists new file mode 100644 index 0000000..e69de29 diff --git a/Parallel-ForkManager-1.17/blib/arch/auto/Parallel/ForkManager/.exists b/Parallel-ForkManager-1.17/blib/arch/auto/Parallel/ForkManager/.exists new file mode 100644 index 0000000..e69de29 diff --git a/Parallel-ForkManager-1.17/blib/bin/.exists b/Parallel-ForkManager-1.17/blib/bin/.exists new file mode 100644 index 0000000..e69de29 diff --git a/Parallel-ForkManager-1.17/blib/lib/Parallel/.exists b/Parallel-ForkManager-1.17/blib/lib/Parallel/.exists new file mode 100644 index 0000000..e69de29 diff --git a/Parallel-ForkManager-1.17/blib/lib/Parallel/ForkManager.pm b/Parallel-ForkManager-1.17/blib/lib/Parallel/ForkManager.pm new file mode 100644 index 0000000..01db006 --- /dev/null +++ b/Parallel-ForkManager-1.17/blib/lib/Parallel/ForkManager.pm @@ -0,0 +1,852 @@ +package Parallel::ForkManager; +our $AUTHORITY = 'cpan:DLUX'; +# ABSTRACT: A simple parallel processing fork manager +$Parallel::ForkManager::VERSION = '1.17'; +use POSIX ":sys_wait_h"; +use Storable qw(store retrieve); +use File::Spec; +use File::Temp (); +use File::Path (); +use Carp; + +use strict; + +sub new { + my ($c,$processes,$tempdir)=@_; + + my $h={ + max_proc => $processes, + processes => {}, + in_child => 0, + parent_pid => $$, + auto_cleanup => ($tempdir ? 0 : 1), + waitpid_blocking_sleep => 1, + }; + + + # determine temporary directory for storing data structures + # add it to Parallel::ForkManager object so children can use it + # We don't let it clean up so it won't do it in the child process + # but we have our own DESTROY to do that. + if (not defined($tempdir) or not length($tempdir)) { + $tempdir = File::Temp::tempdir(CLEANUP => 0); + } + die qq|Temporary directory "$tempdir" doesn't exist or is not a directory.| unless (-e $tempdir && -d _); # ensure temp dir exists and is indeed a directory + $h->{tempdir} = $tempdir; + + return bless($h,ref($c)||$c); +}; + +sub start { + my ($s,$identification)=@_; + + die "Cannot start another process while you are in the child process" + if $s->{in_child}; + while ($s->{max_proc} && ( keys %{ $s->{processes} } ) >= $s->{max_proc}) { + $s->on_wait; + $s->wait_one_child(defined $s->{on_wait_period} ? &WNOHANG : undef); + }; + $s->wait_children; + if ($s->{max_proc}) { + my $pid=fork(); + die "Cannot fork: $!" if !defined $pid; + if ($pid) { + $s->{processes}->{$pid}=$identification; + $s->on_start($pid,$identification); + } else { + $s->{in_child}=1 if !$pid; + } + return $pid; + } else { + $s->{processes}->{$$}=$identification; + $s->on_start($$,$identification); + return 0; # Simulating the child which returns 0 + } +} + +sub finish { + my ($s, $x, $r)=@_; + + if ( $s->{in_child} ) { + if (defined($r)) { # store the child's data structure + my $storable_tempfile = File::Spec->catfile($s->{tempdir}, 'Parallel-ForkManager-' . $s->{parent_pid} . '-' . $$ . '.txt'); + my $stored = eval { return &store($r, $storable_tempfile); }; + + # handle Storables errors, IE logcarp or carp returning undef, or die (via logcroak or croak) + if (not $stored or $@) { + warn(qq|The storable module was unable to store the child's data structure to the temp file "$storable_tempfile": | . join(', ', $@)); + } + } + CORE::exit($x || 0); + } + if ($s->{max_proc} == 0) { # max_proc == 0 + $s->on_finish($$, $x ,$s->{processes}->{$$}, 0, 0, $r); + delete $s->{processes}->{$$}; + } + return 0; +} + +sub wait_children { + my ($s)=@_; + + return if !keys %{$s->{processes}}; + my $kid; + do { + $kid = $s->wait_one_child(&WNOHANG); + } while defined $kid and ( $kid > 0 or $kid < -1 ); # AS 5.6/Win32 returns negative PIDs +}; + +*wait_childs=*wait_children; # compatibility +*reap_finished_children=*wait_children; # behavioral synonym for clarity + +sub wait_one_child { + my ($s,$par)=@_; + + my $kid; + while (1) { + $kid = $s->_waitpid(-1,$par||=0); + + last unless defined $kid; + + last if $kid == 0 || $kid == -1; # AS 5.6/Win32 returns negative PIDs + redo if !exists $s->{processes}->{$kid}; + my $id = delete $s->{processes}->{$kid}; + + # retrieve child data structure, if any + my $retrieved = undef; + my $storable_tempfile = File::Spec->catfile($s->{tempdir}, 'Parallel-ForkManager-' . $$ . '-' . $kid . '.txt'); + if (-e $storable_tempfile) { # child has option of not storing anything, so we need to see if it did or not + $retrieved = eval { return &retrieve($storable_tempfile); }; + + # handle Storables errors + if (not $retrieved or $@) { + warn(qq|The storable module was unable to retrieve the child's data structure from the temporary file "$storable_tempfile": | . join(', ', $@)); + } + + # clean up after ourselves + unlink $storable_tempfile; + } + + $s->on_finish( $kid, $? >> 8 , $id, $? & 0x7f, $? & 0x80 ? 1 : 0, $retrieved); + last; + } + $kid; +}; + +sub wait_all_children { + my ($s)=@_; + + while (keys %{ $s->{processes} }) { + $s->on_wait; + $s->wait_one_child(defined $s->{on_wait_period} ? &WNOHANG : undef); + }; +} + +*wait_all_childs=*wait_all_children; # compatibility; + +sub max_procs { $_[0]->{max_proc}; } + +sub is_child { $_[0]->{in_child} } + +sub is_parent { !$_[0]->{in_child} } + +sub running_procs { + my $self = shift; + + my @pids = keys %{ $self->{processes} }; + return @pids; +} + +sub wait_for_available_procs { + my( $self, $nbr ) = @_; + $nbr ||= 1; + + croak "nbr processes '$nbr' higher than the max nbr of processes (@{[ $self->max_procs ]})" + if $nbr > $self->max_procs; + + $self->wait_one_child until $self->max_procs - $self->running_procs >= $nbr; +} + +sub run_on_finish { + my ($s,$code,$pid)=@_; + + $s->{on_finish}->{$pid || 0}=$code; +} + +sub on_finish { + my ($s,$pid,@par)=@_; + + my $code=$s->{on_finish}->{$pid} || $s->{on_finish}->{0} or return 0; + $code->($pid,@par); +}; + +sub run_on_wait { + my ($s,$code, $period)=@_; + + $s->{on_wait}=$code; + $s->{on_wait_period} = $period; +} + +sub on_wait { + my ($s)=@_; + + if(ref($s->{on_wait}) eq 'CODE') { + $s->{on_wait}->(); + if (defined $s->{on_wait_period}) { + local $SIG{CHLD} = sub { } if ! defined $SIG{CHLD}; + select undef, undef, undef, $s->{on_wait_period} + }; + }; +}; + +sub run_on_start { + my ($s,$code)=@_; + + $s->{on_start}=$code; +} + +sub on_start { + my ($s,@par)=@_; + + $s->{on_start}->(@par) if ref($s->{on_start}) eq 'CODE'; +}; + +sub set_max_procs { + my ($s, $mp)=@_; + + $s->{max_proc} = $mp; +} + +sub set_waitpid_blocking_sleep { + my( $self, $period ) = @_; + $self->{waitpid_blocking_sleep} = $period; +} + +sub waitpid_blocking_sleep { + $_[0]->{waitpid_blocking_sleep}; +} + +sub _waitpid { # Call waitpid() in the standard Unix fashion. + my( $self, undef, $flag ) = @_; + + return $flag ? $self->_waitpid_non_blocking : $self->_waitpid_blocking; +} + +sub _waitpid_non_blocking { + my $self = shift; + + for my $pid ( $self->running_procs ) { + my $p = waitpid $pid, &WNOHANG or next; + + return $pid if $p != -1; + + warn "child process '$pid' disappeared. A call to `waitpid` outside of Parallel::ForkManager might have reaped it.\n"; + # it's gone. let's clean the process entry + delete $self->{processes}{$pid}; + } + + return; +} + +sub _waitpid_blocking { + my $self = shift; + + # pseudo-blocking + if( my $sleep_period = $self->{waitpid_blocking_sleep} ) { + while() { + my $pid = $self->_waitpid_non_blocking; + + return $pid if defined $pid; + + return unless $self->running_procs; + + select undef, undef, undef, $sleep_period; + } + } + + return waitpid -1, 0; +} + +sub DESTROY { + my ($self) = @_; + + if ($self->{auto_cleanup} && $self->{parent_pid} == $$ && -d $self->{tempdir}) { + File::Path::remove_tree($self->{tempdir}); + } +} + +1; + +__END__ + +=pod + +=encoding UTF-8 + +=head1 NAME + +Parallel::ForkManager - A simple parallel processing fork manager + +=head1 VERSION + +version 1.17 + +=head1 SYNOPSIS + + use Parallel::ForkManager; + + my $pm = Parallel::ForkManager->new($MAX_PROCESSES); + + DATA_LOOP: + foreach my $data (@all_data) { + # Forks and returns the pid for the child: + my $pid = $pm->start and next DATA_LOOP; + + ... do some work with $data in the child process ... + + $pm->finish; # Terminates the child process + } + +=head1 DESCRIPTION + +This module is intended for use in operations that can be done in parallel +where the number of processes to be forked off should be limited. Typical +use is a downloader which will be retrieving hundreds/thousands of files. + +The code for a downloader would look something like this: + + use LWP::Simple; + use Parallel::ForkManager; + + ... + + my @links=( + ["http://www.foo.bar/rulez.data","rulez_data.txt"], + ["http://new.host/more_data.doc","more_data.doc"], + ... + ); + + ... + + # Max 30 processes for parallel download + my $pm = Parallel::ForkManager->new(30); + + LINKS: + foreach my $linkarray (@links) { + $pm->start and next LINKS; # do the fork + + my ($link, $fn) = @$linkarray; + warn "Cannot get $fn from $link" + if getstore($link, $fn) != RC_OK; + + $pm->finish; # do the exit in the child process + } + $pm->wait_all_children; + +First you need to instantiate the ForkManager with the "new" constructor. +You must specify the maximum number of processes to be created. If you +specify 0, then NO fork will be done; this is good for debugging purposes. + +Next, use $pm->start to do the fork. $pm returns 0 for the child process, +and child pid for the parent process (see also L). +The "and next" skips the internal loop in the parent process. NOTE: +$pm->start dies if the fork fails. + +$pm->finish terminates the child process (assuming a fork was done in the +"start"). + +NOTE: You cannot use $pm->start if you are already in the child process. +If you want to manage another set of subprocesses in the child process, +you must instantiate another Parallel::ForkManager object! + +=head1 METHODS + +The comment letter indicates where the method should be run. P for parent, +C for child. + +=over 5 + +=item new $processes + +Instantiate a new Parallel::ForkManager object. You must specify the maximum +number of children to fork off. If you specify 0 (zero), then no children +will be forked. This is intended for debugging purposes. + +The optional second parameter, $tempdir, is only used if you want the +children to send back a reference to some data (see RETRIEVING DATASTRUCTURES +below). If not provided, it is set via a call to L::tempdir(). + +The new method will die if the temporary directory does not exist or it is not +a directory. + +=item start [ $process_identifier ] + +This method does the fork. It returns the pid of the child process for +the parent, and 0 for the child process. If the $processes parameter +for the constructor is 0 then, assuming you're in the child process, +$pm->start simply returns 0. + +An optional $process_identifier can be provided to this method... It is used by +the "run_on_finish" callback (see CALLBACKS) for identifying the finished +process. + +=item finish [ $exit_code [, $data_structure_reference] ] + +Closes the child process by exiting and accepts an optional exit code +(default exit code is 0) which can be retrieved in the parent via callback. +If the second optional parameter is provided, the child attempts to send +it's contents back to the parent. If you use the program in debug mode +($processes == 0), this method just calls the callback. + +If the $data_structure_reference is provided, then it is serialized and +passed to the parent process. See RETRIEVING DATASTRUCTURES for more info. + +=item set_max_procs $processes + +Allows you to set a new maximum number of children to maintain. + +=item wait_all_children + +You can call this method to wait for all the processes which have been +forked. This is a blocking wait. + +=item reap_finished_children + +This is a non-blocking call to reap children and execute callbacks independent +of calls to "start" or "wait_all_children". Use this in scenarios where "start" +is called infrequently but you would like the callbacks executed quickly. + +=item is_parent + +Returns C if within the parent or C if within the child. + +=item is_child + +Returns C if within the child or C if within the parent. + +=item max_procs + +Returns the maximal number of processes the object will fork. + +=item running_procs + +Returns the pids of the forked processes currently monitored by the +C. Note that children are still reported as running +until the fork manager harvest them, via the next call to +C or C. + + my @pids = $pm->running_procs; + + my $nbr_children =- $pm->running_procs; + +=item wait_for_available_procs( $n ) + +Wait until C<$n> available process slots are available. +If C<$n> is not given, defaults to I<1>. + +=item waitpid_blocking_sleep + +Returns the sleep period, in seconds, of the pseudo-blocking calls. The sleep +period can be a fraction of second. + +Returns C<0> if disabled. + +Defaults to 1 second. + +See I for more details. + +=item set_waitpid_blocking_sleep $seconds + +Sets the the sleep period, in seconds, of the pseudo-blocking calls. +Set to C<0> to disable. + +See I for more details. + +=back + +=head1 CALLBACKS + +You can define callbacks in the code, which are called on events like starting +a process or upon finish. Declare these before the first call to start(). + +The callbacks can be defined with the following methods: + +=over 4 + +=item run_on_finish $code [, $pid ] + +You can define a subroutine which is called when a child is terminated. It is +called in the parent process. + +The parameters of the $code are the following: + + - pid of the process, which is terminated + - exit code of the program + - identification of the process (if provided in the "start" method) + - exit signal (0-127: signal name) + - core dump (1 if there was core dump at exit) + - datastructure reference or undef (see RETRIEVING DATASTRUCTURES) + +=item run_on_start $code + +You can define a subroutine which is called when a child is started. It called +after the successful startup of a child in the parent process. + +The parameters of the $code are the following: + + - pid of the process which has been started + - identification of the process (if provided in the "start" method) + +=item run_on_wait $code, [$period] + +You can define a subroutine which is called when the child process needs to wait +for the startup. If $period is not defined, then one call is done per +child. If $period is defined, then $code is called periodically and the +module waits for $period seconds between the two calls. Note, $period can be +fractional number also. The exact "$period seconds" is not guaranteed, +signals can shorten and the process scheduler can make it longer (on busy +systems). + +The $code called in the "start" and the "wait_all_children" method also. + +No parameters are passed to the $code on the call. + +=back + +=head1 BLOCKING CALLS + +When it comes to waiting for child processes to terminate, C is between +a fork and a hard place (if you excuse the terrible pun). The underlying Perl C function +that the module relies on can block until either one specific or any child process +terminate, but not for a process part of a given group. + +This means that the module can do one of two things when it waits for +one of its child processes to terminate: + +=over + +=item Only wait for its own child processes + +This is done via a loop using a C non-blocking call and a sleep statement. +The code does something along the lines of + + while(1) { + if ( any of the P::FM child process terminated ) { + return its pid + } + + sleep $sleep_period + } + +This is the default behavior that the module will use. +This is not the most efficient way to wait for child processes, but it's +the safest way to ensure that C won't interfere with +any other part of the codebase. + +The sleep period is set via the method C. + +=item Block until any process terminate + +Alternatively, C can call C such that it will +block until any child process terminate. If the child process was not one of +the monitored subprocesses, the wait will resume. This is more efficient, but mean +that C can captures (and discards) the termination notification that a different +part of the code might be waiting for. + +If this is a race condition +that doesn't apply to your codebase, you can set the +I period to C<0>, which will enable C call blocking. + + my $pm = Parallel::ForkManager->new( 4 ); + + $pm->set_waitpid_blocking_sleep(0); # true blocking calls enabled + + for ( 1..100 ) { + $pm->start and next; + + ...; # do work + + $pm->finish; + } + +=back + +=head1 RETRIEVING DATASTRUCTURES from child processes + +The ability for the parent to retrieve data structures is new as of version +0.7.6. + +Each child process may optionally send 1 data structure back to the parent. +By data structure, we mean a reference to a string, hash or array. The +contents of the data structure are written out to temporary files on disc +using the L modules' store() method. The reference is then +retrieved from within the code you send to the run_on_finish callback. + +The data structure can be any scalar perl data structure which makes sense: +string, numeric value or a reference to an array, hash or object. + +There are 2 steps involved in retrieving data structures: + +1) A reference to the data structure the child wishes to send back to the +parent is provided as the second argument to the finish() call. It is up +to the child to decide whether or not to send anything back to the parent. + +2) The data structure reference is retrieved using the callback provided in +the run_on_finish() method. + +Keep in mind that data structure retrieval is not the same as returning a +data structure from a method call. That is not what actually occurs. The +data structure referenced in a given child process is serialized and +written out to a file by L. The file is subsequently read back +into memory and a new data structure belonging to the parent process is +created. Please consider the performance penality it can imply, so try to +keep the returned structure small. + +=head1 EXAMPLES + +=head2 Parallel get + +This small example can be used to get URLs in parallel. + + use Parallel::ForkManager; + use LWP::Simple; + + my $pm = Parallel::ForkManager->new(10); + + LINKS: + for my $link (@ARGV) { + $pm->start and next LINKS; + my ($fn) = $link =~ /^.*\/(.*?)$/; + if (!$fn) { + warn "Cannot determine filename from $fn\n"; + } else { + $0 .= " " . $fn; + print "Getting $fn from $link\n"; + my $rc = getstore($link, $fn); + print "$link downloaded. response code: $rc\n"; + }; + $pm->finish; + }; + +=head2 Callbacks + +Example of a program using callbacks to get child exit codes: + + use strict; + use Parallel::ForkManager; + + my $max_procs = 5; + my @names = qw( Fred Jim Lily Steve Jessica Bob Dave Christine Rico Sara ); + # hash to resolve PID's back to child specific information + + my $pm = Parallel::ForkManager->new($max_procs); + + # Setup a callback for when a child finishes up so we can + # get it's exit code + $pm->run_on_finish( sub { + my ($pid, $exit_code, $ident) = @_; + print "** $ident just got out of the pool ". + "with PID $pid and exit code: $exit_code\n"; + }); + + $pm->run_on_start( sub { + my ($pid, $ident)=@_; + print "** $ident started, pid: $pid\n"; + }); + + $pm->run_on_wait( sub { + print "** Have to wait for one children ...\n" + }, + 0.5 + ); + + NAMES: + foreach my $child ( 0 .. $#names ) { + my $pid = $pm->start($names[$child]) and next NAMES; + + # This code is the child process + print "This is $names[$child], Child number $child\n"; + sleep ( 2 * $child ); + print "$names[$child], Child $child is about to get out...\n"; + sleep 1; + $pm->finish($child); # pass an exit code to finish + } + + print "Waiting for Children...\n"; + $pm->wait_all_children; + print "Everybody is out of the pool!\n"; + +=head2 Data structure retrieval + +In this simple example, each child sends back a string reference. + + use Parallel::ForkManager 0.7.6; + use strict; + + my $pm = Parallel::ForkManager->new(2, '/server/path/to/temp/dir/'); + + # data structure retrieval and handling + $pm -> run_on_finish ( # called BEFORE the first call to start() + sub { + my ($pid, $exit_code, $ident, $exit_signal, $core_dump, $data_structure_reference) = @_; + + # retrieve data structure from child + if (defined($data_structure_reference)) { # children are not forced to send anything + my $string = ${$data_structure_reference}; # child passed a string reference + print "$string\n"; + } + else { # problems occuring during storage or retrieval will throw a warning + print qq|No message received from child process $pid!\n|; + } + } + ); + + # prep random statement components + my @foods = ('chocolate', 'ice cream', 'peanut butter', 'pickles', 'pizza', 'bacon', 'pancakes', 'spaghetti', 'cookies'); + my @preferences = ('loves', q|can't stand|, 'always wants more', 'will walk 100 miles for', 'only eats', 'would starve rather than eat'); + + # run the parallel processes + PERSONS: + foreach my $person (qw(Fred Wilma Ernie Bert Lucy Ethel Curly Moe Larry)) { + $pm->start() and next PERSONS; + + # generate a random statement about food preferences + my $statement = $person . ' ' . $preferences[int(rand @preferences)] . ' ' . $foods[int(rand @foods)]; + + # send it back to the parent process + $pm->finish(0, \$statement); # note that it's a scalar REFERENCE, not the scalar itself + } + $pm->wait_all_children; + +A second datastructure retrieval example demonstrates how children decide +whether or not to send anything back, what to send and how the parent should +process whatever is retrieved. + +=for example begin + + use Parallel::ForkManager 0.7.6; + use Data::Dumper; # to display the data structures retrieved. + use strict; + + my $pm = Parallel::ForkManager->new(20); # using the system temp dir $L run_on_finish ( + sub { + my ($pid, $exit_code, $ident, $exit_signal, $core_dump, $data_structure_reference) = @_; + + # see what the child sent us, if anything + if (defined($data_structure_reference)) { # test rather than assume child sent anything + my $reftype = ref($data_structure_reference); + print qq|ident "$ident" returned a "$reftype" reference.\n\n|; + if (1) { # simple on/off switch to display the contents + print &Dumper($data_structure_reference) . qq|end of "$ident" sent structure\n\n|; + } + + # we can also collect retrieved data structures for processing after all children have exited + $retrieved_responses{$ident} = $data_structure_reference; + } else { + print qq|ident "$ident" did not send anything.\n\n|; + } + } + ); + + # generate a list of instructions + my @instructions = ( # a unique identifier and what the child process should send + {'name' => '%ENV keys as a string', 'send' => 'keys'}, + {'name' => 'Send Nothing'}, # not instructing the child to send anything back to the parent + {'name' => 'Childs %ENV', 'send' => 'all'}, + {'name' => 'Child chooses randomly', 'send' => 'random'}, + {'name' => 'Invalid send instructions', 'send' => 'Na Na Nana Na'}, + {'name' => 'ENV values in an array', 'send' => 'values'}, + ); + + INSTRUCTS: + foreach my $instruction (@instructions) { + $pm->start($instruction->{'name'}) and next INSTRUCTS; # this time we are using an explicit, unique child process identifier + + # last step in child processing + $pm->finish(0) unless $instruction->{'send'}; # no data structure is sent unless this child is told what to send. + + if ($instruction->{'send'} eq 'keys') { + $pm->finish(0, \join(', ', keys %ENV)); + + } elsif ($instruction->{'send'} eq 'values') { + $pm->finish(0, [values %ENV]); # kinda useless without knowing which keys they belong to... + + } elsif ($instruction->{'send'} eq 'all') { + $pm->finish(0, \%ENV); # remember, we are not "returning" anything, just copying the hash to disc + + # demonstrate clearly that the child determines what type of reference to send + } elsif ($instruction->{'send'} eq 'random') { + my $string = q|I'm just a string.|; + my @array = qw(I am an array); + my %hash = (type => 'associative array', synonym => 'hash', cool => 'very :)'); + my $return_choice = ('string', 'array', 'hash')[int(rand 3)]; # randomly choose return data type + $pm->finish(0, \$string) if ($return_choice eq 'string'); + $pm->finish(0, \@array) if ($return_choice eq 'array'); + $pm->finish(0, \%hash) if ($return_choice eq 'hash'); + + # as a responsible child, inform parent that their instruction was invalid + } else { + $pm->finish(0, \qq|Invalid instructions: "$instruction->{'send'}".|); # ordinarily I wouldn't include invalid input in a response... + } + } + $pm->wait_all_children; # blocks until all forked processes have exited + + # post fork processing of returned data structures + for (sort keys %retrieved_responses) { + print qq|Post processing "$_"...\n|; + } + +=for example end + +=head1 BUGS AND LIMITATIONS + +Do not use Parallel::ForkManager in an environment, where other child +processes can affect the run of the main program, so using this module +is not recommended in an environment where fork() / wait() is already used. + +If you want to use more than one copies of the Parallel::ForkManager, then +you have to make sure that all children processes are terminated, before you +use the second object in the main program. + +You are free to use a new copy of Parallel::ForkManager in the child +processes, although I don't think it makes sense. + +=head1 CREDITS + + Michael Gang (bug report) + Noah Robin (documentation tweaks) + Chuck Hirstius (callback exit status, example) + Grant Hopwood (win32 port) + Mark Southern (bugfix) + Ken Clarke (datastructure retrieval) + +=head1 AUTHORS + +=over 4 + +=item * + +dLux (Szabó, Balázs) + +=item * + +Yanick Champoux + +=item * + +Gabor Szabo + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 2000 by Balázs Szabó. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut diff --git a/Parallel-ForkManager-1.17/blib/lib/auto/Parallel/ForkManager/.exists b/Parallel-ForkManager-1.17/blib/lib/auto/Parallel/ForkManager/.exists new file mode 100644 index 0000000..e69de29 diff --git a/Parallel-ForkManager-1.17/blib/man1/.exists b/Parallel-ForkManager-1.17/blib/man1/.exists new file mode 100644 index 0000000..e69de29 diff --git a/Parallel-ForkManager-1.17/blib/man3/.exists b/Parallel-ForkManager-1.17/blib/man3/.exists new file mode 100644 index 0000000..e69de29 diff --git a/Parallel-ForkManager-1.17/blib/man3/Parallel::ForkManager.3pm b/Parallel-ForkManager-1.17/blib/man3/Parallel::ForkManager.3pm new file mode 100644 index 0000000..d74d293 --- /dev/null +++ b/Parallel-ForkManager-1.17/blib/man3/Parallel::ForkManager.3pm @@ -0,0 +1,680 @@ +.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +. ds C` +. ds C' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.\" +.\" Avoid warning from groff about undefined register 'F'. +.de IX +.. +.nr rF 0 +.if \n(.g .if rF .nr rF 1 +.if (\n(rF:(\n(.g==0)) \{ +. if \nF \{ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. if !\nF==2 \{ +. nr % 0 +. nr F 2 +. \} +. \} +.\} +.rr rF +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "Parallel::ForkManager 3pm" +.TH Parallel::ForkManager 3pm "2015-11-28" "perl v5.18.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +Parallel::ForkManager \- A simple parallel processing fork manager +.SH "VERSION" +.IX Header "VERSION" +version 1.17 +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 1 +\& use Parallel::ForkManager; +\& +\& my $pm = Parallel::ForkManager\->new($MAX_PROCESSES); +\& +\& DATA_LOOP: +\& foreach my $data (@all_data) { +\& # Forks and returns the pid for the child: +\& my $pid = $pm\->start and next DATA_LOOP; +\& +\& ... do some work with $data in the child process ... +\& +\& $pm\->finish; # Terminates the child process +\& } +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +This module is intended for use in operations that can be done in parallel +where the number of processes to be forked off should be limited. Typical +use is a downloader which will be retrieving hundreds/thousands of files. +.PP +The code for a downloader would look something like this: +.PP +.Vb 2 +\& use LWP::Simple; +\& use Parallel::ForkManager; +\& +\& ... +\& +\& my @links=( +\& ["http://www.foo.bar/rulez.data","rulez_data.txt"], +\& ["http://new.host/more_data.doc","more_data.doc"], +\& ... +\& ); +\& +\& ... +\& +\& # Max 30 processes for parallel download +\& my $pm = Parallel::ForkManager\->new(30); +\& +\& LINKS: +\& foreach my $linkarray (@links) { +\& $pm\->start and next LINKS; # do the fork +\& +\& my ($link, $fn) = @$linkarray; +\& warn "Cannot get $fn from $link" +\& if getstore($link, $fn) != RC_OK; +\& +\& $pm\->finish; # do the exit in the child process +\& } +\& $pm\->wait_all_children; +.Ve +.PP +First you need to instantiate the ForkManager with the \*(L"new\*(R" constructor. +You must specify the maximum number of processes to be created. If you +specify 0, then \s-1NO\s0 fork will be done; this is good for debugging purposes. +.PP +Next, use \f(CW$pm\fR\->start to do the fork. \f(CW$pm\fR returns 0 for the child process, +and child pid for the parent process (see also \*(L"\fIfork()\fR\*(R" in \fIperlfunc\fR\|(1p)). +The \*(L"and next\*(R" skips the internal loop in the parent process. \s-1NOTE:\s0 +\&\f(CW$pm\fR\->start dies if the fork fails. +.PP +\&\f(CW$pm\fR\->finish terminates the child process (assuming a fork was done in the +\&\*(L"start\*(R"). +.PP +\&\s-1NOTE:\s0 You cannot use \f(CW$pm\fR\->start if you are already in the child process. +If you want to manage another set of subprocesses in the child process, +you must instantiate another Parallel::ForkManager object! +.SH "METHODS" +.IX Header "METHODS" +The comment letter indicates where the method should be run. P for parent, +C for child. +.ie n .IP "new $processes" 5 +.el .IP "new \f(CW$processes\fR" 5 +.IX Item "new $processes" +Instantiate a new Parallel::ForkManager object. You must specify the maximum +number of children to fork off. If you specify 0 (zero), then no children +will be forked. This is intended for debugging purposes. +.Sp +The optional second parameter, \f(CW$tempdir\fR, is only used if you want the +children to send back a reference to some data (see \s-1RETRIEVING DATASTRUCTURES\s0 +below). If not provided, it is set via a call to File::Temp::\fItempdir()\fR. +.Sp +The new method will die if the temporary directory does not exist or it is not +a directory. +.ie n .IP "start [ $process_identifier ]" 5 +.el .IP "start [ \f(CW$process_identifier\fR ]" 5 +.IX Item "start [ $process_identifier ]" +This method does the fork. It returns the pid of the child process for +the parent, and 0 for the child process. If the \f(CW$processes\fR parameter +for the constructor is 0 then, assuming you're in the child process, +\&\f(CW$pm\fR\->start simply returns 0. +.Sp +An optional \f(CW$process_identifier\fR can be provided to this method... It is used by +the \*(L"run_on_finish\*(R" callback (see \s-1CALLBACKS\s0) for identifying the finished +process. +.ie n .IP "finish [ $exit_code [, $data_structure_reference] ]" 5 +.el .IP "finish [ \f(CW$exit_code\fR [, \f(CW$data_structure_reference\fR] ]" 5 +.IX Item "finish [ $exit_code [, $data_structure_reference] ]" +Closes the child process by exiting and accepts an optional exit code +(default exit code is 0) which can be retrieved in the parent via callback. +If the second optional parameter is provided, the child attempts to send +it's contents back to the parent. If you use the program in debug mode +($processes == 0), this method just calls the callback. +.Sp +If the \f(CW$data_structure_reference\fR is provided, then it is serialized and +passed to the parent process. See \s-1RETRIEVING DATASTRUCTURES\s0 for more info. +.ie n .IP "set_max_procs $processes" 5 +.el .IP "set_max_procs \f(CW$processes\fR" 5 +.IX Item "set_max_procs $processes" +Allows you to set a new maximum number of children to maintain. +.IP "wait_all_children" 5 +.IX Item "wait_all_children" +You can call this method to wait for all the processes which have been +forked. This is a blocking wait. +.IP "reap_finished_children" 5 +.IX Item "reap_finished_children" +This is a non-blocking call to reap children and execute callbacks independent +of calls to \*(L"start\*(R" or \*(L"wait_all_children\*(R". Use this in scenarios where \*(L"start\*(R" +is called infrequently but you would like the callbacks executed quickly. +.IP "is_parent" 5 +.IX Item "is_parent" +Returns \f(CW\*(C`true\*(C'\fR if within the parent or \f(CW\*(C`false\*(C'\fR if within the child. +.IP "is_child" 5 +.IX Item "is_child" +Returns \f(CW\*(C`true\*(C'\fR if within the child or \f(CW\*(C`false\*(C'\fR if within the parent. +.IP "max_procs" 5 +.IX Item "max_procs" +Returns the maximal number of processes the object will fork. +.IP "running_procs" 5 +.IX Item "running_procs" +Returns the pids of the forked processes currently monitored by the +\&\f(CW\*(C`Parallel::ForkManager\*(C'\fR. Note that children are still reported as running +until the fork manager harvest them, via the next call to +\&\f(CW\*(C`start\*(C'\fR or \f(CW\*(C`wait_all_children\*(C'\fR. +.Sp +.Vb 1 +\& my @pids = $pm\->running_procs; +\& +\& my $nbr_children =\- $pm\->running_procs; +.Ve +.ie n .IP "wait_for_available_procs( $n )" 5 +.el .IP "wait_for_available_procs( \f(CW$n\fR )" 5 +.IX Item "wait_for_available_procs( $n )" +Wait until \f(CW$n\fR available process slots are available. +If \f(CW$n\fR is not given, defaults to \fI1\fR. +.IP "waitpid_blocking_sleep" 5 +.IX Item "waitpid_blocking_sleep" +Returns the sleep period, in seconds, of the pseudo-blocking calls. The sleep +period can be a fraction of second. +.Sp +Returns \f(CW0\fR if disabled. +.Sp +Defaults to 1 second. +.Sp +See \fI\s-1BLOCKING CALLS\s0\fR for more details. +.ie n .IP "set_waitpid_blocking_sleep $seconds" 5 +.el .IP "set_waitpid_blocking_sleep \f(CW$seconds\fR" 5 +.IX Item "set_waitpid_blocking_sleep $seconds" +Sets the the sleep period, in seconds, of the pseudo-blocking calls. +Set to \f(CW0\fR to disable. +.Sp +See \fI\s-1BLOCKING CALLS\s0\fR for more details. +.SH "CALLBACKS" +.IX Header "CALLBACKS" +You can define callbacks in the code, which are called on events like starting +a process or upon finish. Declare these before the first call to \fIstart()\fR. +.PP +The callbacks can be defined with the following methods: +.ie n .IP "run_on_finish $code [, $pid ]" 4 +.el .IP "run_on_finish \f(CW$code\fR [, \f(CW$pid\fR ]" 4 +.IX Item "run_on_finish $code [, $pid ]" +You can define a subroutine which is called when a child is terminated. It is +called in the parent process. +.Sp +The parameters of the \f(CW$code\fR are the following: +.Sp +.Vb 6 +\& \- pid of the process, which is terminated +\& \- exit code of the program +\& \- identification of the process (if provided in the "start" method) +\& \- exit signal (0\-127: signal name) +\& \- core dump (1 if there was core dump at exit) +\& \- datastructure reference or undef (see RETRIEVING DATASTRUCTURES) +.Ve +.ie n .IP "run_on_start $code" 4 +.el .IP "run_on_start \f(CW$code\fR" 4 +.IX Item "run_on_start $code" +You can define a subroutine which is called when a child is started. It called +after the successful startup of a child in the parent process. +.Sp +The parameters of the \f(CW$code\fR are the following: +.Sp +.Vb 2 +\& \- pid of the process which has been started +\& \- identification of the process (if provided in the "start" method) +.Ve +.ie n .IP "run_on_wait $code, [$period]" 4 +.el .IP "run_on_wait \f(CW$code\fR, [$period]" 4 +.IX Item "run_on_wait $code, [$period]" +You can define a subroutine which is called when the child process needs to wait +for the startup. If \f(CW$period\fR is not defined, then one call is done per +child. If \f(CW$period\fR is defined, then \f(CW$code\fR is called periodically and the +module waits for \f(CW$period\fR seconds between the two calls. Note, \f(CW$period\fR can be +fractional number also. The exact \*(L"$period seconds\*(R" is not guaranteed, +signals can shorten and the process scheduler can make it longer (on busy +systems). +.Sp +The \f(CW$code\fR called in the \*(L"start\*(R" and the \*(L"wait_all_children\*(R" method also. +.Sp +No parameters are passed to the \f(CW$code\fR on the call. +.SH "BLOCKING CALLS" +.IX Header "BLOCKING CALLS" +When it comes to waiting for child processes to terminate, \f(CW\*(C`Parallel::ForkManager\*(C'\fR is between +a fork and a hard place (if you excuse the terrible pun). The underlying Perl \f(CW\*(C`waitpid\*(C'\fR function +that the module relies on can block until either one specific or any child process +terminate, but not for a process part of a given group. +.PP +This means that the module can do one of two things when it waits for +one of its child processes to terminate: +.IP "Only wait for its own child processes" 4 +.IX Item "Only wait for its own child processes" +This is done via a loop using a \f(CW\*(C`waitpid\*(C'\fR non-blocking call and a sleep statement. +The code does something along the lines of +.Sp +.Vb 4 +\& while(1) { +\& if ( any of the P::FM child process terminated ) { +\& return its pid +\& } +\& +\& sleep $sleep_period +\& } +.Ve +.Sp +This is the default behavior that the module will use. +This is not the most efficient way to wait for child processes, but it's +the safest way to ensure that \f(CW\*(C`Parallel::ForkManager\*(C'\fR won't interfere with +any other part of the codebase. +.Sp +The sleep period is set via the method \f(CW\*(C`set_waitpid_blocking_sleep\*(C'\fR. +.IP "Block until any process terminate" 4 +.IX Item "Block until any process terminate" +Alternatively, \f(CW\*(C`Parallel::ForkManager\*(C'\fR can call \f(CW\*(C`waitpid\*(C'\fR such that it will +block until any child process terminate. If the child process was not one of +the monitored subprocesses, the wait will resume. This is more efficient, but mean +that \f(CW\*(C`P::FM\*(C'\fR can captures (and discards) the termination notification that a different +part of the code might be waiting for. +.Sp +If this is a race condition +that doesn't apply to your codebase, you can set the +\&\fIwaitpid_blocking_sleep\fR period to \f(CW0\fR, which will enable \f(CW\*(C`waitpid\*(C'\fR call blocking. +.Sp +.Vb 1 +\& my $pm = Parallel::ForkManager\->new( 4 ); +\& +\& $pm\->set_waitpid_blocking_sleep(0); # true blocking calls enabled +\& +\& for ( 1..100 ) { +\& $pm\->start and next; +\& +\& ...; # do work +\& +\& $pm\->finish; +\& } +.Ve +.SH "RETRIEVING DATASTRUCTURES from child processes" +.IX Header "RETRIEVING DATASTRUCTURES from child processes" +The ability for the parent to retrieve data structures is new as of version +0.7.6. +.PP +Each child process may optionally send 1 data structure back to the parent. +By data structure, we mean a reference to a string, hash or array. The +contents of the data structure are written out to temporary files on disc +using the Storable modules' \fIstore()\fR method. The reference is then +retrieved from within the code you send to the run_on_finish callback. +.PP +The data structure can be any scalar perl data structure which makes sense: +string, numeric value or a reference to an array, hash or object. +.PP +There are 2 steps involved in retrieving data structures: +.PP +1) A reference to the data structure the child wishes to send back to the +parent is provided as the second argument to the \fIfinish()\fR call. It is up +to the child to decide whether or not to send anything back to the parent. +.PP +2) The data structure reference is retrieved using the callback provided in +the \fIrun_on_finish()\fR method. +.PP +Keep in mind that data structure retrieval is not the same as returning a +data structure from a method call. That is not what actually occurs. The +data structure referenced in a given child process is serialized and +written out to a file by Storable. The file is subsequently read back +into memory and a new data structure belonging to the parent process is +created. Please consider the performance penality it can imply, so try to +keep the returned structure small. +.SH "EXAMPLES" +.IX Header "EXAMPLES" +.SS "Parallel get" +.IX Subsection "Parallel get" +This small example can be used to get URLs in parallel. +.PP +.Vb 2 +\& use Parallel::ForkManager; +\& use LWP::Simple; +\& +\& my $pm = Parallel::ForkManager\->new(10); +\& +\& LINKS: +\& for my $link (@ARGV) { +\& $pm\->start and next LINKS; +\& my ($fn) = $link =~ /^.*\e/(.*?)$/; +\& if (!$fn) { +\& warn "Cannot determine filename from $fn\en"; +\& } else { +\& $0 .= " " . $fn; +\& print "Getting $fn from $link\en"; +\& my $rc = getstore($link, $fn); +\& print "$link downloaded. response code: $rc\en"; +\& }; +\& $pm\->finish; +\& }; +.Ve +.SS "Callbacks" +.IX Subsection "Callbacks" +Example of a program using callbacks to get child exit codes: +.PP +.Vb 2 +\& use strict; +\& use Parallel::ForkManager; +\& +\& my $max_procs = 5; +\& my @names = qw( Fred Jim Lily Steve Jessica Bob Dave Christine Rico Sara ); +\& # hash to resolve PID\*(Aqs back to child specific information +\& +\& my $pm = Parallel::ForkManager\->new($max_procs); +\& +\& # Setup a callback for when a child finishes up so we can +\& # get it\*(Aqs exit code +\& $pm\->run_on_finish( sub { +\& my ($pid, $exit_code, $ident) = @_; +\& print "** $ident just got out of the pool ". +\& "with PID $pid and exit code: $exit_code\en"; +\& }); +\& +\& $pm\->run_on_start( sub { +\& my ($pid, $ident)=@_; +\& print "** $ident started, pid: $pid\en"; +\& }); +\& +\& $pm\->run_on_wait( sub { +\& print "** Have to wait for one children ...\en" +\& }, +\& 0.5 +\& ); +\& +\& NAMES: +\& foreach my $child ( 0 .. $#names ) { +\& my $pid = $pm\->start($names[$child]) and next NAMES; +\& +\& # This code is the child process +\& print "This is $names[$child], Child number $child\en"; +\& sleep ( 2 * $child ); +\& print "$names[$child], Child $child is about to get out...\en"; +\& sleep 1; +\& $pm\->finish($child); # pass an exit code to finish +\& } +\& +\& print "Waiting for Children...\en"; +\& $pm\->wait_all_children; +\& print "Everybody is out of the pool!\en"; +.Ve +.SS "Data structure retrieval" +.IX Subsection "Data structure retrieval" +In this simple example, each child sends back a string reference. +.PP +.Vb 2 +\& use Parallel::ForkManager 0.7.6; +\& use strict; +\& +\& my $pm = Parallel::ForkManager\->new(2, \*(Aq/server/path/to/temp/dir/\*(Aq); +\& +\& # data structure retrieval and handling +\& $pm \-> run_on_finish ( # called BEFORE the first call to start() +\& sub { +\& my ($pid, $exit_code, $ident, $exit_signal, $core_dump, $data_structure_reference) = @_; +\& +\& # retrieve data structure from child +\& if (defined($data_structure_reference)) { # children are not forced to send anything +\& my $string = ${$data_structure_reference}; # child passed a string reference +\& print "$string\en"; +\& } +\& else { # problems occuring during storage or retrieval will throw a warning +\& print qq|No message received from child process $pid!\en|; +\& } +\& } +\& ); +\& +\& # prep random statement components +\& my @foods = (\*(Aqchocolate\*(Aq, \*(Aqice cream\*(Aq, \*(Aqpeanut butter\*(Aq, \*(Aqpickles\*(Aq, \*(Aqpizza\*(Aq, \*(Aqbacon\*(Aq, \*(Aqpancakes\*(Aq, \*(Aqspaghetti\*(Aq, \*(Aqcookies\*(Aq); +\& my @preferences = (\*(Aqloves\*(Aq, q|can\*(Aqt stand|, \*(Aqalways wants more\*(Aq, \*(Aqwill walk 100 miles for\*(Aq, \*(Aqonly eats\*(Aq, \*(Aqwould starve rather than eat\*(Aq); +\& +\& # run the parallel processes +\& PERSONS: +\& foreach my $person (qw(Fred Wilma Ernie Bert Lucy Ethel Curly Moe Larry)) { +\& $pm\->start() and next PERSONS; +\& +\& # generate a random statement about food preferences +\& my $statement = $person . \*(Aq \*(Aq . $preferences[int(rand @preferences)] . \*(Aq \*(Aq . $foods[int(rand @foods)]; +\& +\& # send it back to the parent process +\& $pm\->finish(0, \e$statement); # note that it\*(Aqs a scalar REFERENCE, not the scalar itself +\& } +\& $pm\->wait_all_children; +.Ve +.PP +A second datastructure retrieval example demonstrates how children decide +whether or not to send anything back, what to send and how the parent should +process whatever is retrieved. +.PP +.Vb 3 +\& use Parallel::ForkManager 0.7.6; +\& use Data::Dumper; # to display the data structures retrieved. +\& use strict; +\& +\& my $pm = Parallel::ForkManager\->new(20); # using the system temp dir $L run_on_finish ( +\& sub { +\& my ($pid, $exit_code, $ident, $exit_signal, $core_dump, $data_structure_reference) = @_; +\& +\& # see what the child sent us, if anything +\& if (defined($data_structure_reference)) { # test rather than assume child sent anything +\& my $reftype = ref($data_structure_reference); +\& print qq|ident "$ident" returned a "$reftype" reference.\en\en|; +\& if (1) { # simple on/off switch to display the contents +\& print &Dumper($data_structure_reference) . qq|end of "$ident" sent structure\en\en|; +\& } +\& +\& # we can also collect retrieved data structures for processing after all children have exited +\& $retrieved_responses{$ident} = $data_structure_reference; +\& } else { +\& print qq|ident "$ident" did not send anything.\en\en|; +\& } +\& } +\& ); +\& +\& # generate a list of instructions +\& my @instructions = ( # a unique identifier and what the child process should send +\& {\*(Aqname\*(Aq => \*(Aq%ENV keys as a string\*(Aq, \*(Aqsend\*(Aq => \*(Aqkeys\*(Aq}, +\& {\*(Aqname\*(Aq => \*(AqSend Nothing\*(Aq}, # not instructing the child to send anything back to the parent +\& {\*(Aqname\*(Aq => \*(AqChilds %ENV\*(Aq, \*(Aqsend\*(Aq => \*(Aqall\*(Aq}, +\& {\*(Aqname\*(Aq => \*(AqChild chooses randomly\*(Aq, \*(Aqsend\*(Aq => \*(Aqrandom\*(Aq}, +\& {\*(Aqname\*(Aq => \*(AqInvalid send instructions\*(Aq, \*(Aqsend\*(Aq => \*(AqNa Na Nana Na\*(Aq}, +\& {\*(Aqname\*(Aq => \*(AqENV values in an array\*(Aq, \*(Aqsend\*(Aq => \*(Aqvalues\*(Aq}, +\& ); +\& +\& INSTRUCTS: +\& foreach my $instruction (@instructions) { +\& $pm\->start($instruction\->{\*(Aqname\*(Aq}) and next INSTRUCTS; # this time we are using an explicit, unique child process identifier +\& +\& # last step in child processing +\& $pm\->finish(0) unless $instruction\->{\*(Aqsend\*(Aq}; # no data structure is sent unless this child is told what to send. +\& +\& if ($instruction\->{\*(Aqsend\*(Aq} eq \*(Aqkeys\*(Aq) { +\& $pm\->finish(0, \ejoin(\*(Aq, \*(Aq, keys %ENV)); +\& +\& } elsif ($instruction\->{\*(Aqsend\*(Aq} eq \*(Aqvalues\*(Aq) { +\& $pm\->finish(0, [values %ENV]); # kinda useless without knowing which keys they belong to... +\& +\& } elsif ($instruction\->{\*(Aqsend\*(Aq} eq \*(Aqall\*(Aq) { +\& $pm\->finish(0, \e%ENV); # remember, we are not "returning" anything, just copying the hash to disc +\& +\& # demonstrate clearly that the child determines what type of reference to send +\& } elsif ($instruction\->{\*(Aqsend\*(Aq} eq \*(Aqrandom\*(Aq) { +\& my $string = q|I\*(Aqm just a string.|; +\& my @array = qw(I am an array); +\& my %hash = (type => \*(Aqassociative array\*(Aq, synonym => \*(Aqhash\*(Aq, cool => \*(Aqvery :)\*(Aq); +\& my $return_choice = (\*(Aqstring\*(Aq, \*(Aqarray\*(Aq, \*(Aqhash\*(Aq)[int(rand 3)]; # randomly choose return data type +\& $pm\->finish(0, \e$string) if ($return_choice eq \*(Aqstring\*(Aq); +\& $pm\->finish(0, \e@array) if ($return_choice eq \*(Aqarray\*(Aq); +\& $pm\->finish(0, \e%hash) if ($return_choice eq \*(Aqhash\*(Aq); +\& +\& # as a responsible child, inform parent that their instruction was invalid +\& } else { +\& $pm\->finish(0, \eqq|Invalid instructions: "$instruction\->{\*(Aqsend\*(Aq}".|); # ordinarily I wouldn\*(Aqt include invalid input in a response... +\& } +\& } +\& $pm\->wait_all_children; # blocks until all forked processes have exited +\& +\& # post fork processing of returned data structures +\& for (sort keys %retrieved_responses) { +\& print qq|Post processing "$_"...\en|; +\& } +.Ve +.SH "BUGS AND LIMITATIONS" +.IX Header "BUGS AND LIMITATIONS" +Do not use Parallel::ForkManager in an environment, where other child +processes can affect the run of the main program, so using this module +is not recommended in an environment where \fIfork()\fR / \fIwait()\fR is already used. +.PP +If you want to use more than one copies of the Parallel::ForkManager, then +you have to make sure that all children processes are terminated, before you +use the second object in the main program. +.PP +You are free to use a new copy of Parallel::ForkManager in the child +processes, although I don't think it makes sense. +.SH "CREDITS" +.IX Header "CREDITS" +.Vb 6 +\& Michael Gang (bug report) +\& Noah Robin (documentation tweaks) +\& Chuck Hirstius (callback exit status, example) +\& Grant Hopwood (win32 port) +\& Mark Southern (bugfix) +\& Ken Clarke (datastructure retrieval) +.Ve +.SH "AUTHORS" +.IX Header "AUTHORS" +.IP "\(bu" 4 +dLux (Szabo\*', Bala\*'zs) +.IP "\(bu" 4 +Yanick Champoux +.IP "\(bu" 4 +Gabor Szabo +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +This software is copyright (c) 2000 by Bala\*'zs Szabo\*'. +.PP +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. diff --git a/Parallel-ForkManager-1.17/blib/script/.exists b/Parallel-ForkManager-1.17/blib/script/.exists new file mode 100644 index 0000000..e69de29 diff --git a/Parallel-ForkManager-1.17/cpanfile b/Parallel-ForkManager-1.17/cpanfile new file mode 100644 index 0000000..728c435 --- /dev/null +++ b/Parallel-ForkManager-1.17/cpanfile @@ -0,0 +1,33 @@ +requires "Carp" => "0"; +requires "File::Path" => "0"; +requires "File::Spec" => "0"; +requires "File::Temp" => "0"; +requires "POSIX" => "0"; +requires "Storable" => "0"; +requires "strict" => "0"; + +on 'test' => sub { + requires "ExtUtils::MakeMaker" => "0"; + requires "File::Spec" => "0"; + requires "IO::Handle" => "0"; + requires "IPC::Open3" => "0"; + requires "Test::More" => "0.94"; + requires "Test::Warn" => "0"; + requires "perl" => "5.006"; + requires "warnings" => "0"; +}; + +on 'test' => sub { + recommends "CPAN::Meta" => "2.120900"; +}; + +on 'configure' => sub { + requires "ExtUtils::MakeMaker" => "0"; +}; + +on 'develop' => sub { + requires "Test::More" => "0.96"; + requires "Test::PAUSE::Permissions" => "0"; + requires "Test::Vars" => "0"; + requires "warnings" => "0"; +}; diff --git a/Parallel-ForkManager-1.17/doap.xml b/Parallel-ForkManager-1.17/doap.xml new file mode 100644 index 0000000..19ee374 --- /dev/null +++ b/Parallel-ForkManager-1.17/doap.xml @@ -0,0 +1,231 @@ + + + Parallel-ForkManager + A simple parallel processing fork manager + + + dLux (Szabó, Balázs) + + + + + + Yanick Champoux + + + + + + Gabor Szabo + + + + + + Ninebit + + + + + + Shlomi Fish + + + + + + + + + + + + + + + 0.7.1 + 2001-04-26 + + + + + 0.7.2 + 2001-05-14 + + + + + 0.7.3 + 2001-08-24 + + + + + 0.7.4 + 2002-07-04 + + + + + 0.7.5 + 2002-12-25 + + + + + 0.7.6 + 2010-08-15 + + + + + 0.7.7 + 2010-09-28 + + + + + 0.7.8 + 2010-08-25 + + + + + 0.7.9 + 2010-11-01 + + + + + 0.5 + 2000-10-18 + + + + + 0.6 + 2000-11-30 + + + + + 0.7 + 2001-04-04 + + + + + 1.0.0 + 2012-12-23 + + + + + 1.01 + 2012-12-23 + + + + + 1.02 + 2012-12-24 + + + + + 1.03 + 2013-03-06 + + + + + 1.04 + 2013-09-03 + + + + + 1.05 + 2013-09-18 + + + + + 1.06 + 2013-12-24 + + + + + 1.07 + 2014-11-10 + + + + + 1.08 + 2015-01-07 + + + + + 1.09 + 2015-01-08 + + + + + 1.10_1 + 2015-01-22 + + + + + 1.10_2 + 2015-01-25 + + + + + 1.11 + 2015-01-30 + + + + + 1.12 + 2015-02-23 + + + + + 1.13 + 2015-05-11 + + + + + 1.14 + 2015-05-17 + + + + + 1.15 + 2015-07-08 + + + + + 1.16 + 2015-10-08 + + + Perl + diff --git a/Parallel-ForkManager-1.17/examples/callback.pl b/Parallel-ForkManager-1.17/examples/callback.pl new file mode 100755 index 0000000..649ecf6 --- /dev/null +++ b/Parallel-ForkManager-1.17/examples/callback.pl @@ -0,0 +1,48 @@ +#!/usr/bin/perl -w +use lib '.'; +use strict; +use Parallel::ForkManager; + +my $max_procs = 3; +my @names = qw( Fred Jim Lily Steve Jessica Bob ); +# hash to resolve PID's back to child specific information + +my $pm = Parallel::ForkManager->new($max_procs); + +# Setup a callback for when a child finishes up so we can +# get it's exit code +$pm->run_on_finish( + sub { my ($pid, $exit_code, $ident) = @_; + print "** $ident just got out of the pool ". + "with PID $pid and exit code: $exit_code\n"; + } +); + +$pm->run_on_start( + sub { my ($pid,$ident)=@_; + print "** $ident started, pid: $pid\n"; + } +); + +$pm->run_on_wait( + sub { + print "** Have to wait for one children ...\n" + }, + 0.5, +); + +foreach my $child ( 0 .. $#names ) { + my $pid = $pm->start($names[$child]) and next; + + # This code is the child process + print "This is $names[$child], Child number $child\n"; + sleep ( 2 * $child ); + print "$names[$child], Child $child is about to get out...\n"; + sleep 1; + $pm->finish($child); # pass an exit code to finish +} + +print "Waiting for Children...\n"; +$pm->wait_all_children; +print "Everybody is out of the pool!\n"; + diff --git a/Parallel-ForkManager-1.17/examples/callback_data.pl b/Parallel-ForkManager-1.17/examples/callback_data.pl new file mode 100644 index 0000000..97c6cfc --- /dev/null +++ b/Parallel-ForkManager-1.17/examples/callback_data.pl @@ -0,0 +1,42 @@ +#!/usr/bin/perl +use strict; +use warnings; + +use Parallel::ForkManager; + +my $max_procs = 2; +my @names = qw( Fred Jim ); + +my $pm = Parallel::ForkManager->new($max_procs, @ARGV); + +# Setup a callback for when a child finishes up so we can +# get it's exit code and any data it collected +$pm->run_on_finish( sub { + my ($pid, $exit_code, $ident, $exit_signal, $core_dump, $data_structure_reference) = @_; + print "$ident just got out of the pool ". + "with exit code: $exit_code and data: @$data_structure_reference\n"; +}); + +$pm->run_on_start( sub { + my ($pid,$ident)=@_; + print "$ident started\n"; +}); + +foreach my $child ( 0 .. $#names ) { + my $pid = $pm->start($names[$child]) and next; + + # This code is the child process + # We can do here anything and obtain any data. + # The result can be any array or hash. + my @result = ($names[$child], length $names[$child]); + sleep 1+rand(3); + + # pass an exit code and data stucture to finish + $pm->finish($child, \@result ); +} + +#print "Waiting for Children...\n"; +$pm->wait_all_children; +print "Everybody is out of the pool!\n"; + + diff --git a/Parallel-ForkManager-1.17/examples/parallel_get.pl b/Parallel-ForkManager-1.17/examples/parallel_get.pl new file mode 100755 index 0000000..2a88458 --- /dev/null +++ b/Parallel-ForkManager-1.17/examples/parallel_get.pl @@ -0,0 +1,32 @@ +#!/usr/bin/perl +use strict; +use warnings; + +if (not @ARGV) { + die <<"DIE"; +Usage: $0 URL URL... + e.g.: $0 http://cpan.metacpan.org/authors/id/D/DL/DLUX/Parallel-ForkManager-0.7.9.tar.gz +DIE +} + +use Parallel::ForkManager; +use LWP::Simple; + +my $pm = Parallel::ForkManager->new(10); + +for my $link (@ARGV) { + $pm->start and next; + + my ($fn) = $link =~ /^.*\/(.*?)$/; + + if (!$fn) { + warn "Cannot determine filename from $fn\n"; + } else { + $0 .= " $fn"; + print "Getting $fn from $link\n"; + my $rc = getstore($link, $fn); + print "$link downloaded. response code: $rc\n"; + }; + + $pm->finish; +}; diff --git a/Parallel-ForkManager-1.17/lib/Parallel/ForkManager.pm b/Parallel-ForkManager-1.17/lib/Parallel/ForkManager.pm new file mode 100644 index 0000000..01db006 --- /dev/null +++ b/Parallel-ForkManager-1.17/lib/Parallel/ForkManager.pm @@ -0,0 +1,852 @@ +package Parallel::ForkManager; +our $AUTHORITY = 'cpan:DLUX'; +# ABSTRACT: A simple parallel processing fork manager +$Parallel::ForkManager::VERSION = '1.17'; +use POSIX ":sys_wait_h"; +use Storable qw(store retrieve); +use File::Spec; +use File::Temp (); +use File::Path (); +use Carp; + +use strict; + +sub new { + my ($c,$processes,$tempdir)=@_; + + my $h={ + max_proc => $processes, + processes => {}, + in_child => 0, + parent_pid => $$, + auto_cleanup => ($tempdir ? 0 : 1), + waitpid_blocking_sleep => 1, + }; + + + # determine temporary directory for storing data structures + # add it to Parallel::ForkManager object so children can use it + # We don't let it clean up so it won't do it in the child process + # but we have our own DESTROY to do that. + if (not defined($tempdir) or not length($tempdir)) { + $tempdir = File::Temp::tempdir(CLEANUP => 0); + } + die qq|Temporary directory "$tempdir" doesn't exist or is not a directory.| unless (-e $tempdir && -d _); # ensure temp dir exists and is indeed a directory + $h->{tempdir} = $tempdir; + + return bless($h,ref($c)||$c); +}; + +sub start { + my ($s,$identification)=@_; + + die "Cannot start another process while you are in the child process" + if $s->{in_child}; + while ($s->{max_proc} && ( keys %{ $s->{processes} } ) >= $s->{max_proc}) { + $s->on_wait; + $s->wait_one_child(defined $s->{on_wait_period} ? &WNOHANG : undef); + }; + $s->wait_children; + if ($s->{max_proc}) { + my $pid=fork(); + die "Cannot fork: $!" if !defined $pid; + if ($pid) { + $s->{processes}->{$pid}=$identification; + $s->on_start($pid,$identification); + } else { + $s->{in_child}=1 if !$pid; + } + return $pid; + } else { + $s->{processes}->{$$}=$identification; + $s->on_start($$,$identification); + return 0; # Simulating the child which returns 0 + } +} + +sub finish { + my ($s, $x, $r)=@_; + + if ( $s->{in_child} ) { + if (defined($r)) { # store the child's data structure + my $storable_tempfile = File::Spec->catfile($s->{tempdir}, 'Parallel-ForkManager-' . $s->{parent_pid} . '-' . $$ . '.txt'); + my $stored = eval { return &store($r, $storable_tempfile); }; + + # handle Storables errors, IE logcarp or carp returning undef, or die (via logcroak or croak) + if (not $stored or $@) { + warn(qq|The storable module was unable to store the child's data structure to the temp file "$storable_tempfile": | . join(', ', $@)); + } + } + CORE::exit($x || 0); + } + if ($s->{max_proc} == 0) { # max_proc == 0 + $s->on_finish($$, $x ,$s->{processes}->{$$}, 0, 0, $r); + delete $s->{processes}->{$$}; + } + return 0; +} + +sub wait_children { + my ($s)=@_; + + return if !keys %{$s->{processes}}; + my $kid; + do { + $kid = $s->wait_one_child(&WNOHANG); + } while defined $kid and ( $kid > 0 or $kid < -1 ); # AS 5.6/Win32 returns negative PIDs +}; + +*wait_childs=*wait_children; # compatibility +*reap_finished_children=*wait_children; # behavioral synonym for clarity + +sub wait_one_child { + my ($s,$par)=@_; + + my $kid; + while (1) { + $kid = $s->_waitpid(-1,$par||=0); + + last unless defined $kid; + + last if $kid == 0 || $kid == -1; # AS 5.6/Win32 returns negative PIDs + redo if !exists $s->{processes}->{$kid}; + my $id = delete $s->{processes}->{$kid}; + + # retrieve child data structure, if any + my $retrieved = undef; + my $storable_tempfile = File::Spec->catfile($s->{tempdir}, 'Parallel-ForkManager-' . $$ . '-' . $kid . '.txt'); + if (-e $storable_tempfile) { # child has option of not storing anything, so we need to see if it did or not + $retrieved = eval { return &retrieve($storable_tempfile); }; + + # handle Storables errors + if (not $retrieved or $@) { + warn(qq|The storable module was unable to retrieve the child's data structure from the temporary file "$storable_tempfile": | . join(', ', $@)); + } + + # clean up after ourselves + unlink $storable_tempfile; + } + + $s->on_finish( $kid, $? >> 8 , $id, $? & 0x7f, $? & 0x80 ? 1 : 0, $retrieved); + last; + } + $kid; +}; + +sub wait_all_children { + my ($s)=@_; + + while (keys %{ $s->{processes} }) { + $s->on_wait; + $s->wait_one_child(defined $s->{on_wait_period} ? &WNOHANG : undef); + }; +} + +*wait_all_childs=*wait_all_children; # compatibility; + +sub max_procs { $_[0]->{max_proc}; } + +sub is_child { $_[0]->{in_child} } + +sub is_parent { !$_[0]->{in_child} } + +sub running_procs { + my $self = shift; + + my @pids = keys %{ $self->{processes} }; + return @pids; +} + +sub wait_for_available_procs { + my( $self, $nbr ) = @_; + $nbr ||= 1; + + croak "nbr processes '$nbr' higher than the max nbr of processes (@{[ $self->max_procs ]})" + if $nbr > $self->max_procs; + + $self->wait_one_child until $self->max_procs - $self->running_procs >= $nbr; +} + +sub run_on_finish { + my ($s,$code,$pid)=@_; + + $s->{on_finish}->{$pid || 0}=$code; +} + +sub on_finish { + my ($s,$pid,@par)=@_; + + my $code=$s->{on_finish}->{$pid} || $s->{on_finish}->{0} or return 0; + $code->($pid,@par); +}; + +sub run_on_wait { + my ($s,$code, $period)=@_; + + $s->{on_wait}=$code; + $s->{on_wait_period} = $period; +} + +sub on_wait { + my ($s)=@_; + + if(ref($s->{on_wait}) eq 'CODE') { + $s->{on_wait}->(); + if (defined $s->{on_wait_period}) { + local $SIG{CHLD} = sub { } if ! defined $SIG{CHLD}; + select undef, undef, undef, $s->{on_wait_period} + }; + }; +}; + +sub run_on_start { + my ($s,$code)=@_; + + $s->{on_start}=$code; +} + +sub on_start { + my ($s,@par)=@_; + + $s->{on_start}->(@par) if ref($s->{on_start}) eq 'CODE'; +}; + +sub set_max_procs { + my ($s, $mp)=@_; + + $s->{max_proc} = $mp; +} + +sub set_waitpid_blocking_sleep { + my( $self, $period ) = @_; + $self->{waitpid_blocking_sleep} = $period; +} + +sub waitpid_blocking_sleep { + $_[0]->{waitpid_blocking_sleep}; +} + +sub _waitpid { # Call waitpid() in the standard Unix fashion. + my( $self, undef, $flag ) = @_; + + return $flag ? $self->_waitpid_non_blocking : $self->_waitpid_blocking; +} + +sub _waitpid_non_blocking { + my $self = shift; + + for my $pid ( $self->running_procs ) { + my $p = waitpid $pid, &WNOHANG or next; + + return $pid if $p != -1; + + warn "child process '$pid' disappeared. A call to `waitpid` outside of Parallel::ForkManager might have reaped it.\n"; + # it's gone. let's clean the process entry + delete $self->{processes}{$pid}; + } + + return; +} + +sub _waitpid_blocking { + my $self = shift; + + # pseudo-blocking + if( my $sleep_period = $self->{waitpid_blocking_sleep} ) { + while() { + my $pid = $self->_waitpid_non_blocking; + + return $pid if defined $pid; + + return unless $self->running_procs; + + select undef, undef, undef, $sleep_period; + } + } + + return waitpid -1, 0; +} + +sub DESTROY { + my ($self) = @_; + + if ($self->{auto_cleanup} && $self->{parent_pid} == $$ && -d $self->{tempdir}) { + File::Path::remove_tree($self->{tempdir}); + } +} + +1; + +__END__ + +=pod + +=encoding UTF-8 + +=head1 NAME + +Parallel::ForkManager - A simple parallel processing fork manager + +=head1 VERSION + +version 1.17 + +=head1 SYNOPSIS + + use Parallel::ForkManager; + + my $pm = Parallel::ForkManager->new($MAX_PROCESSES); + + DATA_LOOP: + foreach my $data (@all_data) { + # Forks and returns the pid for the child: + my $pid = $pm->start and next DATA_LOOP; + + ... do some work with $data in the child process ... + + $pm->finish; # Terminates the child process + } + +=head1 DESCRIPTION + +This module is intended for use in operations that can be done in parallel +where the number of processes to be forked off should be limited. Typical +use is a downloader which will be retrieving hundreds/thousands of files. + +The code for a downloader would look something like this: + + use LWP::Simple; + use Parallel::ForkManager; + + ... + + my @links=( + ["http://www.foo.bar/rulez.data","rulez_data.txt"], + ["http://new.host/more_data.doc","more_data.doc"], + ... + ); + + ... + + # Max 30 processes for parallel download + my $pm = Parallel::ForkManager->new(30); + + LINKS: + foreach my $linkarray (@links) { + $pm->start and next LINKS; # do the fork + + my ($link, $fn) = @$linkarray; + warn "Cannot get $fn from $link" + if getstore($link, $fn) != RC_OK; + + $pm->finish; # do the exit in the child process + } + $pm->wait_all_children; + +First you need to instantiate the ForkManager with the "new" constructor. +You must specify the maximum number of processes to be created. If you +specify 0, then NO fork will be done; this is good for debugging purposes. + +Next, use $pm->start to do the fork. $pm returns 0 for the child process, +and child pid for the parent process (see also L). +The "and next" skips the internal loop in the parent process. NOTE: +$pm->start dies if the fork fails. + +$pm->finish terminates the child process (assuming a fork was done in the +"start"). + +NOTE: You cannot use $pm->start if you are already in the child process. +If you want to manage another set of subprocesses in the child process, +you must instantiate another Parallel::ForkManager object! + +=head1 METHODS + +The comment letter indicates where the method should be run. P for parent, +C for child. + +=over 5 + +=item new $processes + +Instantiate a new Parallel::ForkManager object. You must specify the maximum +number of children to fork off. If you specify 0 (zero), then no children +will be forked. This is intended for debugging purposes. + +The optional second parameter, $tempdir, is only used if you want the +children to send back a reference to some data (see RETRIEVING DATASTRUCTURES +below). If not provided, it is set via a call to L::tempdir(). + +The new method will die if the temporary directory does not exist or it is not +a directory. + +=item start [ $process_identifier ] + +This method does the fork. It returns the pid of the child process for +the parent, and 0 for the child process. If the $processes parameter +for the constructor is 0 then, assuming you're in the child process, +$pm->start simply returns 0. + +An optional $process_identifier can be provided to this method... It is used by +the "run_on_finish" callback (see CALLBACKS) for identifying the finished +process. + +=item finish [ $exit_code [, $data_structure_reference] ] + +Closes the child process by exiting and accepts an optional exit code +(default exit code is 0) which can be retrieved in the parent via callback. +If the second optional parameter is provided, the child attempts to send +it's contents back to the parent. If you use the program in debug mode +($processes == 0), this method just calls the callback. + +If the $data_structure_reference is provided, then it is serialized and +passed to the parent process. See RETRIEVING DATASTRUCTURES for more info. + +=item set_max_procs $processes + +Allows you to set a new maximum number of children to maintain. + +=item wait_all_children + +You can call this method to wait for all the processes which have been +forked. This is a blocking wait. + +=item reap_finished_children + +This is a non-blocking call to reap children and execute callbacks independent +of calls to "start" or "wait_all_children". Use this in scenarios where "start" +is called infrequently but you would like the callbacks executed quickly. + +=item is_parent + +Returns C if within the parent or C if within the child. + +=item is_child + +Returns C if within the child or C if within the parent. + +=item max_procs + +Returns the maximal number of processes the object will fork. + +=item running_procs + +Returns the pids of the forked processes currently monitored by the +C. Note that children are still reported as running +until the fork manager harvest them, via the next call to +C or C. + + my @pids = $pm->running_procs; + + my $nbr_children =- $pm->running_procs; + +=item wait_for_available_procs( $n ) + +Wait until C<$n> available process slots are available. +If C<$n> is not given, defaults to I<1>. + +=item waitpid_blocking_sleep + +Returns the sleep period, in seconds, of the pseudo-blocking calls. The sleep +period can be a fraction of second. + +Returns C<0> if disabled. + +Defaults to 1 second. + +See I for more details. + +=item set_waitpid_blocking_sleep $seconds + +Sets the the sleep period, in seconds, of the pseudo-blocking calls. +Set to C<0> to disable. + +See I for more details. + +=back + +=head1 CALLBACKS + +You can define callbacks in the code, which are called on events like starting +a process or upon finish. Declare these before the first call to start(). + +The callbacks can be defined with the following methods: + +=over 4 + +=item run_on_finish $code [, $pid ] + +You can define a subroutine which is called when a child is terminated. It is +called in the parent process. + +The parameters of the $code are the following: + + - pid of the process, which is terminated + - exit code of the program + - identification of the process (if provided in the "start" method) + - exit signal (0-127: signal name) + - core dump (1 if there was core dump at exit) + - datastructure reference or undef (see RETRIEVING DATASTRUCTURES) + +=item run_on_start $code + +You can define a subroutine which is called when a child is started. It called +after the successful startup of a child in the parent process. + +The parameters of the $code are the following: + + - pid of the process which has been started + - identification of the process (if provided in the "start" method) + +=item run_on_wait $code, [$period] + +You can define a subroutine which is called when the child process needs to wait +for the startup. If $period is not defined, then one call is done per +child. If $period is defined, then $code is called periodically and the +module waits for $period seconds between the two calls. Note, $period can be +fractional number also. The exact "$period seconds" is not guaranteed, +signals can shorten and the process scheduler can make it longer (on busy +systems). + +The $code called in the "start" and the "wait_all_children" method also. + +No parameters are passed to the $code on the call. + +=back + +=head1 BLOCKING CALLS + +When it comes to waiting for child processes to terminate, C is between +a fork and a hard place (if you excuse the terrible pun). The underlying Perl C function +that the module relies on can block until either one specific or any child process +terminate, but not for a process part of a given group. + +This means that the module can do one of two things when it waits for +one of its child processes to terminate: + +=over + +=item Only wait for its own child processes + +This is done via a loop using a C non-blocking call and a sleep statement. +The code does something along the lines of + + while(1) { + if ( any of the P::FM child process terminated ) { + return its pid + } + + sleep $sleep_period + } + +This is the default behavior that the module will use. +This is not the most efficient way to wait for child processes, but it's +the safest way to ensure that C won't interfere with +any other part of the codebase. + +The sleep period is set via the method C. + +=item Block until any process terminate + +Alternatively, C can call C such that it will +block until any child process terminate. If the child process was not one of +the monitored subprocesses, the wait will resume. This is more efficient, but mean +that C can captures (and discards) the termination notification that a different +part of the code might be waiting for. + +If this is a race condition +that doesn't apply to your codebase, you can set the +I period to C<0>, which will enable C call blocking. + + my $pm = Parallel::ForkManager->new( 4 ); + + $pm->set_waitpid_blocking_sleep(0); # true blocking calls enabled + + for ( 1..100 ) { + $pm->start and next; + + ...; # do work + + $pm->finish; + } + +=back + +=head1 RETRIEVING DATASTRUCTURES from child processes + +The ability for the parent to retrieve data structures is new as of version +0.7.6. + +Each child process may optionally send 1 data structure back to the parent. +By data structure, we mean a reference to a string, hash or array. The +contents of the data structure are written out to temporary files on disc +using the L modules' store() method. The reference is then +retrieved from within the code you send to the run_on_finish callback. + +The data structure can be any scalar perl data structure which makes sense: +string, numeric value or a reference to an array, hash or object. + +There are 2 steps involved in retrieving data structures: + +1) A reference to the data structure the child wishes to send back to the +parent is provided as the second argument to the finish() call. It is up +to the child to decide whether or not to send anything back to the parent. + +2) The data structure reference is retrieved using the callback provided in +the run_on_finish() method. + +Keep in mind that data structure retrieval is not the same as returning a +data structure from a method call. That is not what actually occurs. The +data structure referenced in a given child process is serialized and +written out to a file by L. The file is subsequently read back +into memory and a new data structure belonging to the parent process is +created. Please consider the performance penality it can imply, so try to +keep the returned structure small. + +=head1 EXAMPLES + +=head2 Parallel get + +This small example can be used to get URLs in parallel. + + use Parallel::ForkManager; + use LWP::Simple; + + my $pm = Parallel::ForkManager->new(10); + + LINKS: + for my $link (@ARGV) { + $pm->start and next LINKS; + my ($fn) = $link =~ /^.*\/(.*?)$/; + if (!$fn) { + warn "Cannot determine filename from $fn\n"; + } else { + $0 .= " " . $fn; + print "Getting $fn from $link\n"; + my $rc = getstore($link, $fn); + print "$link downloaded. response code: $rc\n"; + }; + $pm->finish; + }; + +=head2 Callbacks + +Example of a program using callbacks to get child exit codes: + + use strict; + use Parallel::ForkManager; + + my $max_procs = 5; + my @names = qw( Fred Jim Lily Steve Jessica Bob Dave Christine Rico Sara ); + # hash to resolve PID's back to child specific information + + my $pm = Parallel::ForkManager->new($max_procs); + + # Setup a callback for when a child finishes up so we can + # get it's exit code + $pm->run_on_finish( sub { + my ($pid, $exit_code, $ident) = @_; + print "** $ident just got out of the pool ". + "with PID $pid and exit code: $exit_code\n"; + }); + + $pm->run_on_start( sub { + my ($pid, $ident)=@_; + print "** $ident started, pid: $pid\n"; + }); + + $pm->run_on_wait( sub { + print "** Have to wait for one children ...\n" + }, + 0.5 + ); + + NAMES: + foreach my $child ( 0 .. $#names ) { + my $pid = $pm->start($names[$child]) and next NAMES; + + # This code is the child process + print "This is $names[$child], Child number $child\n"; + sleep ( 2 * $child ); + print "$names[$child], Child $child is about to get out...\n"; + sleep 1; + $pm->finish($child); # pass an exit code to finish + } + + print "Waiting for Children...\n"; + $pm->wait_all_children; + print "Everybody is out of the pool!\n"; + +=head2 Data structure retrieval + +In this simple example, each child sends back a string reference. + + use Parallel::ForkManager 0.7.6; + use strict; + + my $pm = Parallel::ForkManager->new(2, '/server/path/to/temp/dir/'); + + # data structure retrieval and handling + $pm -> run_on_finish ( # called BEFORE the first call to start() + sub { + my ($pid, $exit_code, $ident, $exit_signal, $core_dump, $data_structure_reference) = @_; + + # retrieve data structure from child + if (defined($data_structure_reference)) { # children are not forced to send anything + my $string = ${$data_structure_reference}; # child passed a string reference + print "$string\n"; + } + else { # problems occuring during storage or retrieval will throw a warning + print qq|No message received from child process $pid!\n|; + } + } + ); + + # prep random statement components + my @foods = ('chocolate', 'ice cream', 'peanut butter', 'pickles', 'pizza', 'bacon', 'pancakes', 'spaghetti', 'cookies'); + my @preferences = ('loves', q|can't stand|, 'always wants more', 'will walk 100 miles for', 'only eats', 'would starve rather than eat'); + + # run the parallel processes + PERSONS: + foreach my $person (qw(Fred Wilma Ernie Bert Lucy Ethel Curly Moe Larry)) { + $pm->start() and next PERSONS; + + # generate a random statement about food preferences + my $statement = $person . ' ' . $preferences[int(rand @preferences)] . ' ' . $foods[int(rand @foods)]; + + # send it back to the parent process + $pm->finish(0, \$statement); # note that it's a scalar REFERENCE, not the scalar itself + } + $pm->wait_all_children; + +A second datastructure retrieval example demonstrates how children decide +whether or not to send anything back, what to send and how the parent should +process whatever is retrieved. + +=for example begin + + use Parallel::ForkManager 0.7.6; + use Data::Dumper; # to display the data structures retrieved. + use strict; + + my $pm = Parallel::ForkManager->new(20); # using the system temp dir $L run_on_finish ( + sub { + my ($pid, $exit_code, $ident, $exit_signal, $core_dump, $data_structure_reference) = @_; + + # see what the child sent us, if anything + if (defined($data_structure_reference)) { # test rather than assume child sent anything + my $reftype = ref($data_structure_reference); + print qq|ident "$ident" returned a "$reftype" reference.\n\n|; + if (1) { # simple on/off switch to display the contents + print &Dumper($data_structure_reference) . qq|end of "$ident" sent structure\n\n|; + } + + # we can also collect retrieved data structures for processing after all children have exited + $retrieved_responses{$ident} = $data_structure_reference; + } else { + print qq|ident "$ident" did not send anything.\n\n|; + } + } + ); + + # generate a list of instructions + my @instructions = ( # a unique identifier and what the child process should send + {'name' => '%ENV keys as a string', 'send' => 'keys'}, + {'name' => 'Send Nothing'}, # not instructing the child to send anything back to the parent + {'name' => 'Childs %ENV', 'send' => 'all'}, + {'name' => 'Child chooses randomly', 'send' => 'random'}, + {'name' => 'Invalid send instructions', 'send' => 'Na Na Nana Na'}, + {'name' => 'ENV values in an array', 'send' => 'values'}, + ); + + INSTRUCTS: + foreach my $instruction (@instructions) { + $pm->start($instruction->{'name'}) and next INSTRUCTS; # this time we are using an explicit, unique child process identifier + + # last step in child processing + $pm->finish(0) unless $instruction->{'send'}; # no data structure is sent unless this child is told what to send. + + if ($instruction->{'send'} eq 'keys') { + $pm->finish(0, \join(', ', keys %ENV)); + + } elsif ($instruction->{'send'} eq 'values') { + $pm->finish(0, [values %ENV]); # kinda useless without knowing which keys they belong to... + + } elsif ($instruction->{'send'} eq 'all') { + $pm->finish(0, \%ENV); # remember, we are not "returning" anything, just copying the hash to disc + + # demonstrate clearly that the child determines what type of reference to send + } elsif ($instruction->{'send'} eq 'random') { + my $string = q|I'm just a string.|; + my @array = qw(I am an array); + my %hash = (type => 'associative array', synonym => 'hash', cool => 'very :)'); + my $return_choice = ('string', 'array', 'hash')[int(rand 3)]; # randomly choose return data type + $pm->finish(0, \$string) if ($return_choice eq 'string'); + $pm->finish(0, \@array) if ($return_choice eq 'array'); + $pm->finish(0, \%hash) if ($return_choice eq 'hash'); + + # as a responsible child, inform parent that their instruction was invalid + } else { + $pm->finish(0, \qq|Invalid instructions: "$instruction->{'send'}".|); # ordinarily I wouldn't include invalid input in a response... + } + } + $pm->wait_all_children; # blocks until all forked processes have exited + + # post fork processing of returned data structures + for (sort keys %retrieved_responses) { + print qq|Post processing "$_"...\n|; + } + +=for example end + +=head1 BUGS AND LIMITATIONS + +Do not use Parallel::ForkManager in an environment, where other child +processes can affect the run of the main program, so using this module +is not recommended in an environment where fork() / wait() is already used. + +If you want to use more than one copies of the Parallel::ForkManager, then +you have to make sure that all children processes are terminated, before you +use the second object in the main program. + +You are free to use a new copy of Parallel::ForkManager in the child +processes, although I don't think it makes sense. + +=head1 CREDITS + + Michael Gang (bug report) + Noah Robin (documentation tweaks) + Chuck Hirstius (callback exit status, example) + Grant Hopwood (win32 port) + Mark Southern (bugfix) + Ken Clarke (datastructure retrieval) + +=head1 AUTHORS + +=over 4 + +=item * + +dLux (Szabó, Balázs) + +=item * + +Yanick Champoux + +=item * + +Gabor Szabo + +=back + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 2000 by Balázs Szabó. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut diff --git a/Parallel-ForkManager-1.17/pm_to_blib b/Parallel-ForkManager-1.17/pm_to_blib new file mode 100644 index 0000000..e69de29 diff --git a/Parallel-ForkManager-1.17/t/00-compile.t b/Parallel-ForkManager-1.17/t/00-compile.t new file mode 100644 index 0000000..faac267 --- /dev/null +++ b/Parallel-ForkManager-1.17/t/00-compile.t @@ -0,0 +1,51 @@ +use 5.006; +use strict; +use warnings; + +# this test was generated with Dist::Zilla::Plugin::Test::Compile 2.052 + +use Test::More; + +plan tests => 1 + ($ENV{AUTHOR_TESTING} ? 1 : 0); + +my @module_files = ( + 'Parallel/ForkManager.pm' +); + + + +# no fake home requested + +my $inc_switch = -d 'blib' ? '-Mblib' : '-Ilib'; + +use File::Spec; +use IPC::Open3; +use IO::Handle; + +open my $stdin, '<', File::Spec->devnull or die "can't open devnull: $!"; + +my @warnings; +for my $lib (@module_files) +{ + # see L + my $stderr = IO::Handle->new; + + my $pid = open3($stdin, '>&STDERR', $stderr, $^X, $inc_switch, '-e', "require q[$lib]"); + binmode $stderr, ':crlf' if $^O eq 'MSWin32'; + my @_warnings = <$stderr>; + waitpid($pid, 0); + is($?, 0, "$lib loaded ok"); + + if (@_warnings) + { + warn @_warnings; + push @warnings, @_warnings; + } +} + + + +is(scalar(@warnings), 0, 'no warnings found') + or diag 'got warnings: ', ( Test::More->can('explain') ? Test::More::explain(\@warnings) : join("\n", '', @warnings) ) if $ENV{AUTHOR_TESTING}; + + diff --git a/Parallel-ForkManager-1.17/t/00-load.t b/Parallel-ForkManager-1.17/t/00-load.t new file mode 100644 index 0000000..5d2983a --- /dev/null +++ b/Parallel-ForkManager-1.17/t/00-load.t @@ -0,0 +1,41 @@ +use strict; +use warnings; + +use Test::More tests => 4; +use Parallel::ForkManager; +use File::Temp qw(tempdir); + +my @numbers = (1 .. 20); + +for my $processes ( 1, 3 ) { + for my $pseudo_block ( 0, 1 ) { + my $chrono = time; + is_deeply count($processes,$pseudo_block) => \@numbers, + "procs: $processes, pseudo-block: $pseudo_block"; + $chrono = time - $chrono; + diag "time: $chrono seconds"; + }; +} + + +sub count { + my ($concurrency,$blocking_time) = @_; + + my $dir = tempdir(CLEANUP => 1); + + my $fork = Parallel::ForkManager->new( $concurrency ); + $fork->set_waitpid_blocking_sleep( $blocking_time ); + + foreach my $n (@numbers) { + my $pid = $fork->start and next; + open my $fh, '>', "$dir/$n" or die; + close $fh or die; + $fork->finish; + } + $fork->wait_all_children; + opendir my $dh, $dir or die; + my @results = grep { $_ !~ /\./ } readdir $dh; + closedir $dh or die; + return [sort {$a <=> $b} @results]; +} + diff --git a/Parallel-ForkManager-1.17/t/00-report-prereqs.dd b/Parallel-ForkManager-1.17/t/00-report-prereqs.dd new file mode 100644 index 0000000..abfe35e --- /dev/null +++ b/Parallel-ForkManager-1.17/t/00-report-prereqs.dd @@ -0,0 +1,43 @@ +do { my $x = { + 'configure' => { + 'requires' => { + 'ExtUtils::MakeMaker' => '0' + } + }, + 'develop' => { + 'requires' => { + 'Test::More' => '0.96', + 'Test::PAUSE::Permissions' => '0', + 'Test::Vars' => '0', + 'warnings' => '0' + } + }, + 'runtime' => { + 'requires' => { + 'Carp' => '0', + 'File::Path' => '0', + 'File::Spec' => '0', + 'File::Temp' => '0', + 'POSIX' => '0', + 'Storable' => '0', + 'strict' => '0' + } + }, + 'test' => { + 'recommends' => { + 'CPAN::Meta' => '2.120900' + }, + 'requires' => { + 'ExtUtils::MakeMaker' => '0', + 'File::Spec' => '0', + 'IO::Handle' => '0', + 'IPC::Open3' => '0', + 'Test::More' => '0.94', + 'Test::Warn' => '0', + 'perl' => '5.006', + 'warnings' => '0' + } + } + }; + $x; + } \ No newline at end of file diff --git a/Parallel-ForkManager-1.17/t/00-report-prereqs.t b/Parallel-ForkManager-1.17/t/00-report-prereqs.t new file mode 100644 index 0000000..d8d15ba --- /dev/null +++ b/Parallel-ForkManager-1.17/t/00-report-prereqs.t @@ -0,0 +1,183 @@ +#!perl + +use strict; +use warnings; + +# This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.021 + +use Test::More tests => 1; + +use ExtUtils::MakeMaker; +use File::Spec; + +# from $version::LAX +my $lax_version_re = + qr/(?: undef | (?: (?:[0-9]+) (?: \. | (?:\.[0-9]+) (?:_[0-9]+)? )? + | + (?:\.[0-9]+) (?:_[0-9]+)? + ) | (?: + v (?:[0-9]+) (?: (?:\.[0-9]+)+ (?:_[0-9]+)? )? + | + (?:[0-9]+)? (?:\.[0-9]+){2,} (?:_[0-9]+)? + ) + )/x; + +# hide optional CPAN::Meta modules from prereq scanner +# and check if they are available +my $cpan_meta = "CPAN::Meta"; +my $cpan_meta_pre = "CPAN::Meta::Prereqs"; +my $HAS_CPAN_META = eval "require $cpan_meta; $cpan_meta->VERSION('2.120900')" && eval "require $cpan_meta_pre"; ## no critic + +# Verify requirements? +my $DO_VERIFY_PREREQS = 1; + +sub _max { + my $max = shift; + $max = ( $_ > $max ) ? $_ : $max for @_; + return $max; +} + +sub _merge_prereqs { + my ($collector, $prereqs) = @_; + + # CPAN::Meta::Prereqs object + if (ref $collector eq $cpan_meta_pre) { + return $collector->with_merged_prereqs( + CPAN::Meta::Prereqs->new( $prereqs ) + ); + } + + # Raw hashrefs + for my $phase ( keys %$prereqs ) { + for my $type ( keys %{ $prereqs->{$phase} } ) { + for my $module ( keys %{ $prereqs->{$phase}{$type} } ) { + $collector->{$phase}{$type}{$module} = $prereqs->{$phase}{$type}{$module}; + } + } + } + + return $collector; +} + +my @include = qw( + +); + +my @exclude = qw( + +); + +# Add static prereqs to the included modules list +my $static_prereqs = do 't/00-report-prereqs.dd'; + +# Merge all prereqs (either with ::Prereqs or a hashref) +my $full_prereqs = _merge_prereqs( + ( $HAS_CPAN_META ? $cpan_meta_pre->new : {} ), + $static_prereqs +); + +# Add dynamic prereqs to the included modules list (if we can) +my ($source) = grep { -f } 'MYMETA.json', 'MYMETA.yml'; +if ( $source && $HAS_CPAN_META ) { + if ( my $meta = eval { CPAN::Meta->load_file($source) } ) { + $full_prereqs = _merge_prereqs($full_prereqs, $meta->prereqs); + } +} +else { + $source = 'static metadata'; +} + +my @full_reports; +my @dep_errors; +my $req_hash = $HAS_CPAN_META ? $full_prereqs->as_string_hash : $full_prereqs; + +# Add static includes into a fake section +for my $mod (@include) { + $req_hash->{other}{modules}{$mod} = 0; +} + +for my $phase ( qw(configure build test runtime develop other) ) { + next unless $req_hash->{$phase}; + next if ($phase eq 'develop' and not $ENV{AUTHOR_TESTING}); + + for my $type ( qw(requires recommends suggests conflicts modules) ) { + next unless $req_hash->{$phase}{$type}; + + my $title = ucfirst($phase).' '.ucfirst($type); + my @reports = [qw/Module Want Have/]; + + for my $mod ( sort keys %{ $req_hash->{$phase}{$type} } ) { + next if $mod eq 'perl'; + next if grep { $_ eq $mod } @exclude; + + my $file = $mod; + $file =~ s{::}{/}g; + $file .= ".pm"; + my ($prefix) = grep { -e File::Spec->catfile($_, $file) } @INC; + + my $want = $req_hash->{$phase}{$type}{$mod}; + $want = "undef" unless defined $want; + $want = "any" if !$want && $want == 0; + + my $req_string = $want eq 'any' ? 'any version required' : "version '$want' required"; + + if ($prefix) { + my $have = MM->parse_version( File::Spec->catfile($prefix, $file) ); + $have = "undef" unless defined $have; + push @reports, [$mod, $want, $have]; + + if ( $DO_VERIFY_PREREQS && $HAS_CPAN_META && $type eq 'requires' ) { + if ( $have !~ /\A$lax_version_re\z/ ) { + push @dep_errors, "$mod version '$have' cannot be parsed ($req_string)"; + } + elsif ( ! $full_prereqs->requirements_for( $phase, $type )->accepts_module( $mod => $have ) ) { + push @dep_errors, "$mod version '$have' is not in required range '$want'"; + } + } + } + else { + push @reports, [$mod, $want, "missing"]; + + if ( $DO_VERIFY_PREREQS && $type eq 'requires' ) { + push @dep_errors, "$mod is not installed ($req_string)"; + } + } + } + + if ( @reports ) { + push @full_reports, "=== $title ===\n\n"; + + my $ml = _max( map { length $_->[0] } @reports ); + my $wl = _max( map { length $_->[1] } @reports ); + my $hl = _max( map { length $_->[2] } @reports ); + + if ($type eq 'modules') { + splice @reports, 1, 0, ["-" x $ml, "", "-" x $hl]; + push @full_reports, map { sprintf(" %*s %*s\n", -$ml, $_->[0], $hl, $_->[2]) } @reports; + } + else { + splice @reports, 1, 0, ["-" x $ml, "-" x $wl, "-" x $hl]; + push @full_reports, map { sprintf(" %*s %*s %*s\n", -$ml, $_->[0], $wl, $_->[1], $hl, $_->[2]) } @reports; + } + + push @full_reports, "\n"; + } + } +} + +if ( @full_reports ) { + diag "\nVersions for all modules listed in $source (including optional ones):\n\n", @full_reports; +} + +if ( @dep_errors ) { + diag join("\n", + "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n", + "The following REQUIRED prerequisites were not satisfied:\n", + @dep_errors, + "\n" + ); +} + +pass; + +# vim: ts=4 sts=4 sw=4 et: diff --git a/Parallel-ForkManager-1.17/t/01-utf8-all.t b/Parallel-ForkManager-1.17/t/01-utf8-all.t new file mode 100644 index 0000000..4acd4e9 --- /dev/null +++ b/Parallel-ForkManager-1.17/t/01-utf8-all.t @@ -0,0 +1,24 @@ +use strict; +use warnings; + +use Test::More; +use Parallel::ForkManager; + +plan skip_all => 'This is a bug in perl itself on Windows' if $^O eq 'MSWin32'; +# It is broken on 5.16.2 and on blead Perl: +# It was reported to the Perl 5 porters: +# http://www.nntp.perl.org/group/perl.perl5.porters/2012/12/msg196821.html + +eval "use utf8::all"; +plan skip_all => 'Need utf8::all for this test crashing on Windows' if ($@); +plan tests => 1; + +my $fork = Parallel::ForkManager->new( 1 ); +foreach (1) { + my $pid = $fork->start and next; + $fork->finish; +} +$fork->wait_all_children; + +ok(1); + diff --git a/Parallel-ForkManager-1.17/t/02-callback.t b/Parallel-ForkManager-1.17/t/02-callback.t new file mode 100644 index 0000000..652aa00 --- /dev/null +++ b/Parallel-ForkManager-1.17/t/02-callback.t @@ -0,0 +1,22 @@ +use strict; +use warnings; + +use Test::More tests => 2; + +diag 'This test can take 10-20 seconds, please wait. Started at ' . localtime; + +my @out = qx{$^X -Ilib examples/callback.pl}; +$_ =~ s/pid:\s*-?\d+/pid:/g for @out; +$_ =~ s/PID\s*-?\d+/PID/g for @out; +my @wait = grep { /Have to wait for one children/ } @out; +@out = grep { !/Have to wait for one children/ } @out; +@out = sort @out; +cmp_ok scalar(@wait), '>', 10, 'Have to wait for one children at least 10 times'; + + +my @expected = do { open my $fh, '<', 't/callback.txt'; <$fh> }; +$_ =~ s/pid:\s*-?\d+/pid:/g for @expected; +$_ =~ s/PID\s*-?\d+/PID/g for @expected; +@expected = sort @expected; +is_deeply \@out, \@expected, 'callback worked' or diag explain @out; + diff --git a/Parallel-ForkManager-1.17/t/03-callback-data.t b/Parallel-ForkManager-1.17/t/03-callback-data.t new file mode 100644 index 0000000..fc567ff --- /dev/null +++ b/Parallel-ForkManager-1.17/t/03-callback-data.t @@ -0,0 +1,29 @@ +use strict; +use warnings; + +use Test::More 0.94 tests => 2; +use File::Temp qw(tempdir); + +diag 'This test can take 2-6 seconds, please wait. Started at ' . localtime; + + +my @expected = do { open my $fh, '<', 't/callback_data.txt'; <$fh> }; +@expected = sort @expected; + + +subtest direct => sub { + my @out = sort qx{$^X -Ilib examples/callback_data.pl}; + is_deeply \@out, \@expected, 'callback_data worked' or diag explain @out; +}; + +subtest tempdir => sub { + my $dir = tempdir( CLEANUP => 1 ); + my $tempdir = "$dir/abc"; + mkdir $tempdir; + my @out = sort qx{$^X -Ilib examples/callback_data.pl $tempdir}; + is_deeply \@out, \@expected, 'callback_data worked' or diag explain @out; + ok -d $tempdir, 'tempdir was left there'; +}; + + + diff --git a/Parallel-ForkManager-1.17/t/basic-methods.t b/Parallel-ForkManager-1.17/t/basic-methods.t new file mode 100644 index 0000000..ab100d3 --- /dev/null +++ b/Parallel-ForkManager-1.17/t/basic-methods.t @@ -0,0 +1,38 @@ +use strict; +use warnings; + +use Test::More tests => 8; + +use Parallel::ForkManager; + +my $pm = Parallel::ForkManager->new(4); + +for(1..3) { + $pm->start and next; + sleep $_; + $pm->finish; +} + +my $nbr = $pm->running_procs; +my @pids = $pm->running_procs; + +is $pm->max_procs => 4, 'max procs is 4'; + +is $nbr => 3, '3 children'; + +is scalar(@pids) => 3, '3 children'; + +# on Windows they'll be negative +like $_ => qr/^-?\d+$/, "looks like a pid" for @pids; + +$pm->wait_for_available_procs(3); + +is $pm->running_procs => 1, 'only one process left'; + +$pm->wait_all_children; + +is $pm->running_procs => 0, "all done"; + + + + diff --git a/Parallel-ForkManager-1.17/t/callback.txt b/Parallel-ForkManager-1.17/t/callback.txt new file mode 100644 index 0000000..d7a8a45 --- /dev/null +++ b/Parallel-ForkManager-1.17/t/callback.txt @@ -0,0 +1,26 @@ +** Bob just got out of the pool with PID 23400 and exit code: 5 +** Bob started, pid: 23400 +** Fred just got out of the pool with PID 23395 and exit code: 0 +** Fred started, pid: 23395 +** Jessica just got out of the pool with PID 23399 and exit code: 4 +** Jessica started, pid: 23399 +** Jim just got out of the pool with PID 23396 and exit code: 1 +** Jim started, pid: 23396 +** Lily just got out of the pool with PID 23397 and exit code: 2 +** Lily started, pid: 23397 +** Steve just got out of the pool with PID 23398 and exit code: 3 +** Steve started, pid: 23398 +Bob, Child 5 is about to get out... +Everybody is out of the pool! +Fred, Child 0 is about to get out... +Jessica, Child 4 is about to get out... +Jim, Child 1 is about to get out... +Lily, Child 2 is about to get out... +Steve, Child 3 is about to get out... +This is Bob, Child number 5 +This is Fred, Child number 0 +This is Jessica, Child number 4 +This is Jim, Child number 1 +This is Lily, Child number 2 +This is Steve, Child number 3 +Waiting for Children... diff --git a/Parallel-ForkManager-1.17/t/callback_data.txt b/Parallel-ForkManager-1.17/t/callback_data.txt new file mode 100644 index 0000000..ec12c21 --- /dev/null +++ b/Parallel-ForkManager-1.17/t/callback_data.txt @@ -0,0 +1,5 @@ +Fred started +Jim started +Fred just got out of the pool with exit code: 0 and data: Fred 4 +Jim just got out of the pool with exit code: 1 and data: Jim 3 +Everybody is out of the pool! diff --git a/Parallel-ForkManager-1.17/t/waitpid-conflict.t b/Parallel-ForkManager-1.17/t/waitpid-conflict.t new file mode 100644 index 0000000..dcae56f --- /dev/null +++ b/Parallel-ForkManager-1.17/t/waitpid-conflict.t @@ -0,0 +1,38 @@ +use strict; +use warnings; + +use Test::More; + +use Parallel::ForkManager; + +my $pm = Parallel::ForkManager->new(4); + +local $SIG{ALRM} = sub { + fail "test hanging, forever waiting for child process"; + exit 1; +}; + +for ( 1 ) { + $pm->start and next; + sleep 2; + $pm->finish; +} + +my $pid = waitpid -1, 0; + +diag "code outside of P::FM stole $pid"; + +TODO: { + local $TODO = 'MacOS and FreeBDS seem to have issues with this'; + + eval { + alarm 10; + $pm->wait_all_children; + pass "wait_all_children terminated"; + }; + + is $pm->running_procs => 0, "all children are accounted for"; + +} + +done_testing; diff --git a/Parallel-ForkManager-1.17/t/waitpid-waitonechild.t b/Parallel-ForkManager-1.17/t/waitpid-waitonechild.t new file mode 100644 index 0000000..a84ea4e --- /dev/null +++ b/Parallel-ForkManager-1.17/t/waitpid-waitonechild.t @@ -0,0 +1,42 @@ +use strict; +use warnings; + +use Test::More; +use Test::Warn; + +use Parallel::ForkManager; + +my $pm = Parallel::ForkManager->new(4); + +local $SIG{ALRM} = sub { + fail "test hanging, forever waiting for child process"; + exit 1; +}; + +for ( 1 ) { + $pm->start and last; + sleep 2; + $pm->finish; +} + +my $pid = waitpid -1, 0; + +diag "code outside of P::FM stole $pid"; + +TODO: { + local $TODO = 'MacOS and FreeBDS seem to have issues with this'; + + eval { + alarm 10; + warning_like { + $pm->wait_one_child; + } qr/child process '\d+' disappeared. A call to `waitpid` outside of Parallel::ForkManager might have reaped it\./, + "got the missing child warning"; + pass "wait_one_child terminated"; + }; + + is $pm->running_procs => 0, "all children are accounted for"; + +} + +done_testing; diff --git a/Parallel-ForkManager-1.17/t/waitpid_blocking.t b/Parallel-ForkManager-1.17/t/waitpid_blocking.t new file mode 100644 index 0000000..5eabf39 --- /dev/null +++ b/Parallel-ForkManager-1.17/t/waitpid_blocking.t @@ -0,0 +1,31 @@ +use strict; +use warnings; + +use Test::More tests => 1; + +use Parallel::ForkManager; + +my $pm = Parallel::ForkManager->new(2); + +$pm->set_waitpid_blocking_sleep(5); +my $start = time; + +for(1) { + $pm->start and last; + sleep 1; + $pm->finish; +} + +$pm->wait_one_child; + +# if the sleep works correctly, we shouldn't +# check if the child is gone before 5 seconds +# in the future + +cmp_ok abs( 5 - time + $start ), '<=', 2; + + + + + + diff --git a/Parallel-ForkManager-1.17/xt/release/pause-permissions.t b/Parallel-ForkManager-1.17/xt/release/pause-permissions.t new file mode 100644 index 0000000..e18e9a9 --- /dev/null +++ b/Parallel-ForkManager-1.17/xt/release/pause-permissions.t @@ -0,0 +1,13 @@ +use strict; +use warnings; + +# this test was generated with Dist::Zilla::Plugin::Test::PAUSE::Permissions 0.002 + +use Test::More; +BEGIN { + plan skip_all => 'Test::PAUSE::Permissions required for testing pause permissions' + if $] < 5.010; +} +use Test::PAUSE::Permissions; + +all_permissions_ok('yanick'); diff --git a/Parallel-ForkManager-1.17/xt/release/unused-vars.t b/Parallel-ForkManager-1.17/xt/release/unused-vars.t new file mode 100644 index 0000000..e601076 --- /dev/null +++ b/Parallel-ForkManager-1.17/xt/release/unused-vars.t @@ -0,0 +1,14 @@ +#!perl + +use Test::More 0.96 tests => 1; +eval { require Test::Vars }; + +SKIP: { + skip 1 => 'Test::Vars required for testing for unused vars' + if $@; + Test::Vars->import; + + subtest 'unused vars' => sub { +all_vars_ok(); + }; +}; diff --git a/packaging/libparallel-forkmanager-perl.spec b/packaging/libparallel-forkmanager-perl.spec new file mode 100644 index 0000000..1750133 --- /dev/null +++ b/packaging/libparallel-forkmanager-perl.spec @@ -0,0 +1,118 @@ +# +# spec file for package perl-BSSolv +# +# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany. +# +# All modifications and additions to the file contributed by third parties +# remain the property of their copyright owners, unless otherwise agreed +# upon. The license for this file, and modifications and additions to the +# file, is the same license as for the pristine package itself (unless the +# license for the pristine package is not an Open Source License, in which +# case the license is the MIT License). An "Open Source License" is a +# license that conforms to the Open Source Definition (Version 1.9) +# published by the Open Source Initiative. + +# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# + + +Name: libparallel-forkmanager-perl +Version: 1.17 +Release: 1 +Source: %{name}_%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-build + +%if 0%{?mandriva_version} +# force this version on mandriva +BuildRequires: libneon0.26-devel +%endif + +%if 0%{?fedora_version} +BuildRequires: db4-devel +BuildRequires: perl-devel +%endif +%if 0%{?suse_version} +Requires: perl +%if 0%{?suse_version} < 1030 +BuildRequires: expat +%else +BuildRequires: libexpat-devel +%endif +%else +BuildRequires: expat-devel +%endif +%if 0%{?rhel_version} || 0%{?centos_version} +BuildRequires: db4-devel +%endif +BuildRequires: cmake +BuildRequires: gcc-c++ +BuildRequires: perl +BuildRequires: rpm-devel +BuildRequires: xz-devel +BuildRequires: zlib-devel +#RHEL6 moved ExtUtils::MakeMaker outside the main perl package +BuildRequires: perl(ExtUtils::MakeMaker) +# the testsuite uses the check framework +BuildRequires: check-devel +Summary: A new approach to package dependency solving +License: BSD-3-Clause +Group: Development/Libraries/C and C++ +# probably needed for rhel/centos on x86_64 +%if 0%{!?perl_vendorarch} +%define perl_vendorarch %(eval "`%{__perl} -V:installvendorarch`"; echo $installvendorarch) +%endif + +%description +Using a Satisfyability Solver to compute package dependencies. + +%prep +%setup -c + +%build +export CFLAGS="$RPM_OPT_FLAGS" +export CXXFLAGS="$CFLAGS" +CMAKE_FLAGS= +%if 0%{?fedora_version} || 0%{?rhel_version} || 0%{?centos_version} +CMAKE_FLAGS="-DFEDORA=1" +%endif + +%if 0%{?rhel_version} || 0%{?centos_version} +CFLAGS="$CFLAGS -DUSE_OWN_QSORT" +%endif + +#pushd libsolv +#cmake $CMAKE_FLAGS \ +# -DDISABLE_SHARED=1 \ +# -DCMAKE_BUILD_TYPE=Release \ +# -DCMAKE_SKIP_RPATH=1 \ +# -DENABLE_RPMDB=1 \ +# -DENABLE_DEBIAN=1 \ +# -DENABLE_ARCHREPO=1 \ +# -DENABLE_LZMA_COMPRESSION=1 \ +# -DMULTI_SEMANTICS=1 +#pushd src ; make ; popd +#pushd ext ; make ; popd +#popd +pushd Parallel-ForkManager-%{version} ; perl Makefile.PL ; make ; popd + +%install +pushd Parallel-ForkManager-%{version} ; make DESTDIR=$RPM_BUILD_ROOT install ; popd + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) + +%dir %{perl_sitelib}/Parallel +%{perl_sitelib}/Parallel/ForkManager.pm +/usr/share/man/man3/Parallel::ForkManager.3pm.gz +%{perl_sitearch}/auto +%{perl_sitearch}/auto/Parallel +%{perl_sitearch}/auto/Parallel/ForkManager +%exclude %{perl_sitearch}/auto/Parallel/ForkManager/.packlist +%exclude %{perl_archlib}/perllocal.pod +%changelog +* Fri Oct 18 2013 mls@suse.de +- update to libsolv-0.4.0 to get REL_MULTIARCH support + -- 2.34.1