重要的更新:这个问题与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.5Apache下的WriteExcel由于分段错误而死亡,我发现它发生在Spreadsheet::WriteExcel包中的require Parse::RecDescent语句上。
strace显示最后发生的事情是dup‘’ing:
[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;(事实上,我使用的是PerlIO::via::QuotedPrint以外的双模式层,但效果是一样的)
如果我不执行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 serverUpd:相同的代码在过时的Ubuntu8.04+Perl5.8.8+ mod_perl2 2.0.3下运行良好
Upd2: FreeBSD 9.1 +Perl5.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发布于 2013-08-30 16:17:05
如果它在没有binmode集的情况下工作,那么您可能有一个解决方案(如果不是真正的答案,为什么会发生这种情况)。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,而不是为其他文件句柄/套接字设置binmode,直到"bug“(如果是bug)不出现为止。
编辑
由于您的简单和可重复的错误/测试用例,我认为这将得到解决。我构建了一个调试版本的perl来尝试跟踪错误,它在liberperl.so中--在PerlIOBase_dup()中的某个地方。我还在IRC上向知道这一点的人提到了这一点,他们得出结论,这是一个真正的(即可报告的) perl错误。
下面是我运行gdb的方式
(gdb) run -Dx -le 'use PerlIO::via::QuotedPrint; binmode(\*STDERR,
":via(PerlIO::via::QuotedPrint):utf8"); open (ERROR, ">&STDERR");'事情就是这样结束的:
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变得更好了!
https://stackoverflow.com/questions/18533538
复制相似问题