重要更新:问题与 Apache 或 mod_perl 无关。最简单的演示:
> perl -le 'use PerlIO::via::QuotedPrint; binmode(\*STDERR, ":via(PerlIO::via::QuotedPrint):utf8"); open (ERROR, ">&STDERR");'
zsh: segmentation fault perl -le
实际上binmode
是由我的代码和open (ERROR, ">&STDERR");
Parse::RecDescent 执行的。
原始问题:
我在 mod_perl 2.0.5 下的 Spreadsheet::WriteExcel 有问题 Apache 因分段错误而死,我发现它发生 require Parse::RecDescent
在包内的语句上Spreadsheet::WriteExcel
。
strace 表明最后发生的事情是重复 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) ---
我通读了代码Parse::RecDescent
并注意到了类似的语句open (ERROR, ">&STDERR");
好吧,经过一些额外的实验后,我有了这个简约的 Plack 应用程序来重现段错误:
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层PerlIO::via::QuotedPrint
,但是效果是一样的)
如果我不执行binmode(\*STDERR, ":via(PerlIO...
,则 apache 不会出现段错误。
如果我不重复STDERR
,则 apache 不会出现段错误。
如果我两者都做,它会出现段错误。
作为一种解决方法,我可以避免binmode
在 STDERR 上使用,但这并不好。
关于应该在哪里以及如何解决这个问题的任何建议?
谢谢。
我的环境:
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
更新:相同的代码在过时的 Ubuntu 8.04 + perl 5.8.8 + mod_perl2 2.0.3 下运行良好
Upd2:FreeBSD 9.1 + perl 5.14 + mod_perl 2.0.8 -- 段错误重复
uname -a
FreeBSD liruoko.ru 9.1-RELEASE-p5 FreeBSD 9.1-RELEASE-p5 #7 r253740: Sun Jul 28 16:53:08 MSK 2013 roman@thor.cmc.msu.ru:/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