<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>HattaraTecLog &#187; Parallel::Prefork</title>
	<atom:link href="http://teclog.hattara.info/?feed=rss2&#038;tag=parallelprefork" rel="self" type="application/rss+xml" />
	<link>http://teclog.hattara.info</link>
	<description>LinuxネタとかPHPネタとかの技術ログ</description>
	<lastBuildDate>Tue, 18 Nov 2014 12:15:20 +0000</lastBuildDate>
	<language>ja</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.8</generator>
	<item>
		<title>Parallel::Preforkで「cannot start another process while you are in child process」</title>
		<link>http://teclog.hattara.info/?p=380</link>
		<comments>http://teclog.hattara.info/?p=380#comments</comments>
		<pubDate>Tue, 05 Feb 2013 00:06:37 +0000</pubDate>
		<dc:creator><![CDATA[hattara]]></dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[error]]></category>
		<category><![CDATA[Parallel::Prefork]]></category>

		<guid isPermaLink="false">http://teclog.hattara.info/?p=380</guid>
		<description><![CDATA[今日は、perlのParallel::Prefork(Parallel/Prefork.pm)で出たエラーにつ [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>今日は、perlのParallel::Prefork(Parallel/Prefork.pm)で出たエラーについてメモ。<br />
結論からいうと、今回のパターンは、Parallel::Preforkのバージョンと組み方の問題でした。<br />
(※あくまでエラーメッセージの条件説明じゃなく、こんなパターンで出る場合があるよという感じで見てください)</p>
<p>では、簡単なテストスクリプトを書いてみます。</p>
<pre>
#!/usr/local/bin/env perl
use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/Parallel-Prefork-0.08/lib/";
use Parallel::Prefork;

my $pm = Parallel::Prefork->new({
        max_workers => 2,
        trap_signals => {
            TERM => 'TERM',
        },
    });

while ($pm->signal_received ne 'TERM') {
    $pm->start(sub {
        sleep(3);
        warn "end:" . time();
    });
}
$pm->wait_all_children();
</pre>
<p>これを実行すると、</p>
<pre>
cannot start another process while you are in child process at ...../Parallel/Prefork.pm line 42.
</pre>
<p>みたいなエラーが表示されます。</p>
<p>これは、手元にあった0.10未満のバージョンのParallel::Preforkを利用して、<br />
0.10から実装された「- support new style: $pm->start(sub { &#8230; })」の形で<br />
コードを実装してしまっている為です。</p>
<p>【0.10未満のParallel::Prefork】<br />
$pm->start(sub{})に対応していないので、上記のコードだと、<br />
何も処理されずにstartだけしてwhile分がまわります。<br />
ここで問題なのは、Parallel::Prefoxkを正常終了するには、$pm->finishしないといけないという事。<br />
この場合、$pm->start(sub{});で渡した内容が宙に浮きます。そして、finishが走る要素がなくなります。</p>
<pre>
sub start { 
    my $self = shift;
　　　　：
　　　　：
    die 'cannot start another process while you are in child process'
        if $self->{in_child};
　　　　：
}
</pre>
<p>0.10以上のParallel::Preforkを利用している場合には、上記の$pm->start(sub{})の中が<br />
Parallel::Prefork側の$cbに入り、$cb->();実行後に、$self->finish();されているので、問題ない。</p>
<pre>
sub start {
    my ($self, $cb) = @_;
　　　　：
　　　　：
       if ($cb) {
           $cb->();
           $self->finish();
       }
　　　　：
}
</pre>
<p>ということで、コードをそのままに、libの読み込み先を</p>
<pre>
use lib "$FindBin::Bin/Parallel-Prefork-0.08/lib/";
　　　　　　　　　　　　　　　　　　　　　　　　↓
use lib "$FindBin::Bin/Parallel-Prefork-0.13/lib/";
</pre>
<p>に変更したら、正常に動作しました。<br />
まあ、通常はcpanmとかでParallel::Preforkを更新すればいいだけですね。<br />
現時点の最新が、0.13なので、それにしてますが、多分Changesから見ると0.10以降なら何でも動くはず。</p>
<p>【もしも0.08のままいきたいなら】<br />
コードを以下のように$pm->startの引数で渡すのを止めて、<br />
かつ、$pm->finish;を明示的にするように修正すればいいだけですね</p>
<pre>
#!/usr/local/bin/env perl
use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/Parallel-Prefork-0.08/lib/";
use Parallel::Prefork;

my $pm = Parallel::Prefork->new({
        max_workers => 2,
        trap_signals => {
            TERM => 'TERM',
        },
    });

while ($pm->signal_received ne 'TERM') {
    $pm->start;

    sleep(3);
    warn "end:" . time();

    $pm->finish;
}
</pre>
<p>まあ、そもそもが、Parallel::Preforkの0.10以上を利用していたシステムを<br />
0.10未満のサーバに移植した(古いサーバに移設とかあまり無いですよね)とかしないと発生しないので、<br />
この現象を調べる事になる人は、ほとんどいないと思いますけど。</p>
]]></content:encoded>
			<wfw:commentRss>http://teclog.hattara.info/?feed=rss2&#038;p=380</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
