使用 Wx 的 Perl 在调试模式下产生核心转储(选项 -d)

Perl using Wx yields core dump in debug mode (option -d)

我有以下 3 行示例来显示错误:

use strict;
use warnings;
use Wx;

当我 运行 它与 perl -w hue5.pl 时它工作正常。但是,当我添加调试选项并使用 perl -w -d hue5.pl 启动时,出现了一个问题,perl 运行time 崩溃说:

Loading DB routines from perl5db.pl version 1.55 Editor support available.

Enter h or 'h h' for help, or 'man perldebug' for more help.

Wx::CODE(0x5604c197ca80)(/usr/lib64/perl5/vendor_perl/Wx.pm:154): 154: UnsetConstants() if defined &UnsetConstants; double free or corruption (!prev) Aborted (core dumped)

我在 64 位上使用 perl v5.30.3 Linux(最新的 Fedora 版本 31)和从二进制包 perl-Wx-0.9932-15.fc31 安装的 Wx。x86_64.rpm.

还有其他人遇到这个问题吗?

简短版本:卸载软件包 perl-Term-ReadLine-Gnu 解决了问题。

更长的版本:我看到问题并不总是发生。实际上,这似乎取决于进程环境的大小。在调试的某一时刻,我可以通过在 bash 中声明来使崩溃出现(注意:没有 export 问题不会显示)

export SOMEVAR=xyz

然后消失

unset SOMEVAR

最后,在进一步的实验中,我曾经收到一条更详细的失败消息,指向 Readline/Gnu:

Signal SEGV at /usr/lib64/perl5/vendor_perl/Term/ReadLine/Gnu.pm line 504. Term::ReadLine::Gnu::ornaments(Term::ReadLine=HASH(0x5593c12e5190), 1) > called at /usr/lib64/perl5/vendor_perl/Term/ReadLine/Gnu.pm line 301 Term::ReadLine::Gnu::new("Term::ReadLine", "perldb", GLOB(0x5593c062df58), GLOB(0x5593c05c6ea8)) called at /usr/share/perl5/perl5db.pl line 6865 DB::setterm() called at /usr/share/perl5/perl5db.pl line 1849 DB::_DB__read_next_cmd(undef) called at /usr/share/perl5/perl5db.pl line 2789 DB::DB called at f.pl line 5

对于 好奇,我注意到 /usr/lib64/perl5/vendor_perl/Term/ReadLine/Gnu.pm 中的第 504 行是:

return Term::ReadLine::Gnu::XS::ornaments(@_);

为了 更加好奇 我添加了运行生成的 strace 转储,它们仅在 SOMEVAR 的 absence/presence 方面有所不同环境(请注意,名称似乎并不重要,我首先通过观察 OLDPWD 的不同行为来进入环境差异的方向)。

首先没有问题(即没有变量 SOMEVAR),引用加载 Readline/Gnu 库时的行:

stat("/usr/lib65/perl5/vendor_perl/auto/Term/ReadLine/Gnu/XS/autosplit.ix", {st_mode=S_IFREG|0644, st_size=1137, ...}) = 0
openat(AT_FDCWD, "/usr/lib64/perl5/vendor_perl/auto/Term/ReadLine/Gnu/XS/autosplit.ix", O_RDONLY|O_CLOEXEC) = 13
ioctl(13, TCGETS, 0x7fff0a1cac70)       = -1 ENOTTY (Inappropriate ioctl for device)
lseek(13, 0, SEEK_CUR)                  = 0
read(13, "# Index created by AutoSplit for"..., 8192) = 1137
read(13, "", 8192)                      = 0
close(13)                               = 0
lseek(3, 2189, SEEK_SET)                = 2189
lseek(3, 0, SEEK_CUR)                   = 2189
close(3)                                = 0
getuid()                                = 1000
geteuid()                               = 1000
getgid()                                = 1000
getegid()                               = 1000
fcntl(4, F_GETFL)                       = 0x8002 (flags O_RDWR|O_LARGEFILE)
fcntl(5, F_GETFL)                       = 0x8002 (flags O_RDWR|O_LARGEFILE)
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
stat("/home/bernhard/.terminfo", 0x55ec16193000) = -1 ENOENT (No such file or directory)
stat("/etc/terminfo", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat("/usr/share/terminfo", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
access("/etc/terminfo/x/xterm-256color", R_OK) = -1 ENOENT (No such file or directory)
access("/usr/share/terminfo/x/xterm-256color", R_OK) = 0
openat(AT_FDCWD, "/usr/share/terminfo/x/xterm-256color", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=3808, ...}) = 0
read(3, "%[=13=]&[=13=][=13=]5[=13=]10xterm-256color|xterm"..., 32768) = 3808
read(3, "", 28672)                      = 0
close(3)                                = 0
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(1, TIOCGWINSZ, {ws_row=43, ws_col=173, ws_xpixel=0, ws_ypixel=0}) = 0
ioctl(4, TIOCGWINSZ, {ws_row=43, ws_col=173, ws_xpixel=0, ws_ypixel=0}) = 0
ioctl(4, TIOCGWINSZ, {ws_row=43, ws_col=173, ws_xpixel=0, ws_ypixel=0}) = 0
ioctl(4, TIOCSWINSZ, {ws_row=43, ws_col=173, ws_xpixel=0, ws_ypixel=0}) = 0
ioctl(4, TCGETS, {B38400 opost isig icanon echo ...}) = 0
openat(AT_FDCWD, "/home/bernhard/.inputrc", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/inputrc", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=943, ...}) = 0
read(3, "# do not bell on tab-completion\n"..., 943) = 943
close(3)                                = 0
brk(NULL)                               = 0x55ec1640f000
brk(0x55ec16430000)                     = 0x55ec16430000
stat("/usr/lib64/perl5/vendor_perl/auto/Term/ReadLine/Gnu/XS/ornaments.al", {st_mode=S_IFREG|0644, st_size=1351, ...}) = 0
geteuid()                               = 1000
geteuid()                               = 1000
getegid()                               = 1000
getgroups(0, NULL)                      = 2
getgroups(2, [18, 1000])                = 2
stat("/usr/lib64/perl5/vendor_perl/auto/Term/ReadLine/Gnu/XS/ornaments.al", {st_mode=S_IFREG|0644, st_size=1351, ...}) = 0
openat(AT_FDCWD, "/usr/lib64/perl5/vendor_perl/auto/Term/ReadLine/Gnu/XS/ornaments.al", O_RDONLY|O_CLOEXEC) = 3
ioctl(3, TCGETS, 0x7fff0a1cb9d0)        = -1 ENOTTY (Inappropriate ioctl for device)
lseek(3, 0, SEEK_CUR)                   = 0
read(3, "# NOTE: Derived from blib/lib/Te"..., 8192) = 1351
read(3, "", 8192)                       = 0
close(3)                                = 0
getpid()                                = 4060
getpid()                                = 4060
ioctl(4, TIOCGWINSZ, {ws_row=43, ws_col=173, ws_xpixel=0, ws_ypixel=0}) = 0
ioctl(4, TIOCSWINSZ, {ws_row=43, ws_col=173, ws_xpixel=0, ws_ypixel=0}) = 0
ioctl(4, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(4, SNDCTL_TMR_STOP or TCSETSW, {B38400 opost isig -icanon -echo ...}) = 0
rt_sigprocmask(SIG_BLOCK, [HUP INT QUIT ALRM TERM TSTP TTIN TTOU], [], 8) = 0
rt_sigaction(SIGINT, {sa_handler=0x7f4433da2e70, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, 8) = 0
rt_sigaction(SIGTERM, {sa_handler=0x7f4433da2e70, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGHUP, {sa_handler=0x7f4433da2e70, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGQUIT, {sa_handler=0x7f4433da2e70, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGALRM, {sa_handler=0x7f4433da2e70, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGTSTP, {sa_handler=0x7f4433da2e70, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGTTOU, {sa_handler=0x7f4433da2e70, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigaction(SIGTTIN, {sa_handler=0x7f4433da2e70, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigaction(SIGWINCH, {sa_handler=0x7f4433da22f0, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f44490e46b0}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
fstat(5, {st_mode=S_IFCHR|0666, st_rdev=makedev(0x5, 0), ...}) = 0
ioctl(5, TCGETS, {B38400 opost isig -icanon -echo ...}) = 0
write(5, "[4m  DB<1> [24m", 17)   = 17
pselect6(5, [4], NULL, NULL, NULL, {[], 8}) = 1 (in [4])
read(4, "q", 1)                         = 1
select(5, [4], NULL, [4], {tv_sec=0, tv_usec=0}) = 0 (Timeout)
write(5, "q", 1)                        = 1
pselect6(5, [4], NULL, NULL, NULL, {[], 8}) = 1 (in [4])
read(4, "\r", 1)                        = 1
write(5, "\n", 1)                       = 1
ioctl(4, SNDCTL_TMR_STOP or TCSETSW, {B38400 opost isig icanon echo ...}) = 0
rt_sigaction(SIGINT, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, {sa_handler=0x7f4433da2e70, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, 8) = 0
rt_sigaction(SIGTERM, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, {sa_handler=0x7f4433da2e70, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, 8) = 0
rt_sigaction(SIGHUP, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, {sa_handler=0x7f4433da2e70, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, 8) = 0
rt_sigaction(SIGQUIT, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, {sa_handler=0x7f4433da2e70, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, 8) = 0
rt_sigaction(SIGALRM, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, {sa_handler=0x7f4433da2e70, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, 8) = 0
rt_sigaction(SIGTSTP, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, {sa_handler=0x7f4433da2e70, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, 8) = 0
rt_sigaction(SIGTTOU, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, {sa_handler=0x7f4433da2e70, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, 8) = 0
rt_sigaction(SIGTTIN, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, {sa_handler=0x7f4433da2e70, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, 8) = 0
rt_sigaction(SIGWINCH, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7f44490e46b0}, {sa_handler=0x7f4433da22f0, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f44490e46b0}, 8) = 0
close(4)                                = 0
close(5)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

第二个问题(即机智导出变量SOMEVAR),再次仅引用加载Readline/Gnu库时的行:

stat("/usr/lib64/perl5/vendor_perl/auto/Term/ReadLine/Gnu/XS/autosplit.ix", {st_mode=S_IFREG|0644, st_size=1137, ...}) = 0
openat(AT_FDCWD, "/usr/lib64/perl5/vendor_perl/auto/Term/ReadLine/Gnu/XS/autosplit.ix", O_RDONLY|O_CLOEXEC) = 13
ioctl(13, TCGETS, 0x7ffe8bf62e00)       = -1 ENOTTY (Inappropriate ioctl for device)
lseek(13, 0, SEEK_CUR)                  = 0
read(13, "# Index created by AutoSplit for"..., 8192) = 1137
read(13, "", 8192)                      = 0
close(13)                               = 0
lseek(3, 2189, SEEK_SET)                = 2189
lseek(3, 0, SEEK_CUR)                   = 2189
close(3)                                = 0
getuid()                                = 1000
geteuid()                               = 1000
getgid()                                = 1000
getegid()                               = 1000
fcntl(4, F_GETFL)                       = 0x8002 (flags O_RDWR|O_LARGEFILE)
fcntl(5, F_GETFL)                       = 0x8002 (flags O_RDWR|O_LARGEFILE)
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
stat("/home/bernhard/.terminfo", 0x55b600a2b5a0) = -1 ENOENT (No such file or directory)
stat("/etc/terminfo", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat("/usr/share/terminfo", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
access("/etc/terminfo/x/xterm-256color", R_OK) = -1 ENOENT (No such file or directory)
access("/usr/share/terminfo/x/xterm-256color", R_OK) = 0
openat(AT_FDCWD, "/usr/share/terminfo/x/xterm-256color", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=3808, ...}) = 0
read(3, "%[=14=]&[=14=][=14=]5[=14=]10xterm-256color|xterm"..., 32768) = 3808
read(3, "", 28672)                      = 0
close(3)                                = 0
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(1, TIOCGWINSZ, {ws_row=43, ws_col=173, ws_xpixel=0, ws_ypixel=0}) = 0
ioctl(4, TIOCGWINSZ, {ws_row=43, ws_col=173, ws_xpixel=0, ws_ypixel=0}) = 0
writev(2, [{iov_base="double free or corruption (!prev"..., iov_len=33}, {iov_base="\n", iov_len=1}], 2) = 34
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f376a2e3000
rt_sigprocmask(SIG_UNBLOCK, [ABRT], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1], [], 8) = 0
getpid()                                = 4029
gettid()                                = 4029
tgkill(4029, 4029, SIGABRT)             = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGABRT {si_signo=SIGABRT, si_code=SI_TKILL, si_pid=4029, si_uid=1000} ---
+++ killed by SIGABRT (core dumped) +++