2013-08-30 7 views
7

重要なアップデート:この問題は、Apacheまたはmod_perlとは関係ありません。 最も簡単なデモンストレーション:実際binmodebinmode + mod_perl 2.0.5 + Parse :: RecDescent = segmentaion fault

> perl -le 'use PerlIO::via::QuotedPrint; binmode(\*STDERR, ":via(PerlIO::via::QuotedPrint):utf8"); open (ERROR, ">&STDERR");' 
zsh: segmentation fault perl -le 

を解析:: RecDescentのことで私のコードとopen (ERROR, ">&STDERR");によって行われます。


オリジナル質問:

は私が2.0.5 Apacheがセグメンテーションフォールトで死ぬmod_perlの下で、スプレッドシート:: WriteExcelに問題がある、と私はそれがSpreadsheet::WriteExcelパッケージ内require Parse::RecDescent声明に発生することが分かりました。

straceの問題が発生した最後のものはdup'ing STDERRであることを示しています。私はParse::RecDescentのコードを読んで、open (ERROR, ">&STDERR");

まあのようなステートメントを気づい

[pid 31253] dup(2)      = 8 
[pid 31253] ioctl(8, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fffcf66a328) = -1 ENOTTY (Inappropriate ioctl for device) 
[pid 31253] lseek(8, 0, SEEK_CUR)  = 0 
[pid 31253] --- SIGSEGV (Segmentation fault) @ 0 (0) --- 

は、いくつかの追加の実験の後、私はこのミニマルを持っていますセグメンテーションを再現するためのアプリを作る:

use strict; 
use warnings; 

# DANGEROUS 
use PerlIO::via::QuotedPrint; 
binmode(\*STDERR, ":via(PerlIO::via::QuotedPrint):utf8"); 

my $app = sub { 
    my $env = shift; 

    open (ERROR, ">&STDERR"); # segmenatation fault 

    return [ 
     '200', 
     [ 'Content-Type' => 'text/plain' ], 
     [ "hello world" ], 
    ]; 
}; 

$app; 

(実際には以外のbinmodeレイヤーを使用していますでも効果は同じです)

私がbinmode(\*STDERR, ":via(PerlIO...を実行しないと、Apacheはセグメンテーションしません。

私がSTDERRを複製していない場合、Apacheはセグメンテーションしません。

私がその両方を行うと、それはセグメンテーションします。

STDERRでbinmodeを使用することは避けることができますが、それは良くありません。

これをどこでどのように修正するべきですか?

ありがとうございました。

私の環境:

perl -v |grep version 
This is perl 5, version 14, subversion 2 (v5.14.2) built for x86_64-linux-gnu-thread-multi 

uname -a 
Linux thinkpad 3.2.0-32-generiC#51-Ubuntu SMP Wed Sep 26 21:33:09 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux 

lsb_release -c 
Codename:  precise 

dpkg -l |grep mod-perl 
ii libapache2-mod-perl2 2.0.5-5ubuntu1 Integration of perl with the Apache2 web server 

UPD:FreeBSDの9.1 + perlの5.14 + mod_perlの2.0:同じコードが時代遅れのUbuntu 8.04 + perlの5.8.8 + mod_perl2 2.0.3

UPD2の下でうまく動作します。 8 - セグメンテーション違反それはbinmodeセットせずに動作する場合は、おそらくあなたはソリューション(ない場合はこれが起こっている理由に本当の答えを)持っている

uname -a        
FreeBSD liruoko.ru 9.1-RELEASE-p5 FreeBSD 9.1-RELEASE-p5 #7 r253740: Sun Jul 28 16:53:08 MSK 2013  [email protected]:/usr/obj/usr/src/sys/MINI amd64 

pkg info |grep apache      
apache22-itk-mpm-2.2.25  Version 2.2.x of Apache web server with itk MPM. 

pkg info |grep mod_perl    
ap22-mod_perl2-2.0.8,3   Embeds a Perl interpreter in the Apache2 server 

perl -v |grep version 
This is perl 5, version 14, subversion 4 (v5.14.4) built for amd64-freebsd 
+0

詳細情報を入力してください。オペレーティングシステム、Perlのディストリビューションとバージョンは何ですか?ソフトウェアが古くなった場合は、アップグレードするとどうなりますか? – daxim

+0

Ubuntu 12.04(LTS)、perl 5.14、詳細な質問が – Hln

+0

に追加されました。それ以来、Perlとmod_perlの両方には数多くのクラッシュバグを修正したリリースがありました。 mod_perl 2.0.8とperl 5.18.1でクラッシュがまだ発生していますか?はいの場合は、http://perl.apache.org/docs/2.0/devel/debug/c.html#Analyzing_Dumped_Core_Filesを参照してください。 – daxim

答えて

3

を繰り返します。 c.f.perldoc -f binmodeからこの抜粋:それがある場合

On some systems (in general, DOS- and Windows-based systems) binmode() is 
necessary when you're not working with a text file. For the sake of portability 
it is a good idea always to use it when appropriate, and never to use it when it 
isn't appropriate. Also, people can set their I/O to be by default UTF8-encoded 
Unicode, not bytes. 

In other words: regardless of platform, use binmode() on binary data, like 
images, for example. ... 

perldocの独特のスタイルでは、私は(あなたが「バグ」になるまで調整する他人のために特定のファイルハンドル/ソケット用binmodeを設定していない可能性が示唆される可能性があります思い1)は表示されません。

EDIT:あなたのシンプルかつ再現性のあるエラー/テストケースに

おかげで私は、これは固定されますと思います。 perlのデバッグバージョンを作成してエラーをトレースしました。liberperl.so - PerlIOBase_dup()のどこかにあります。 IRCでこれを知っている人にも言及したところ、これは実際の(、すなわちレポート可能)perlバグであると結論付けました。

(gdb) run -Dx -le 'use PerlIO::via::QuotedPrint; binmode(\*STDERR, 
":via(PerlIO::via::QuotedPrint):utf8"); open (ERROR,  ">&STDERR");' 

をし、物事が終わったかこれは::

は、ここで私はgdbを実行した方法です

Program received signal SIGSEGV, Segmentation fault. 
PerlIOBase_dup (f=0x0, o=0x801551060, param=0x0, flags=2) at perlio.c:2307 
2307 PerlIOBase(f)->flags |= PERLIO_F_UTF8; 

乾杯は、あなたがより良いperlを作りましたよ!