【问题标题】:Stream error, while trying to initialize deflate object in Compress::Raw::Zlib::_deflateInit流错误,同时尝试在 Compress::Raw::Zlib::_deflateInit 中初始化 deflate 对象
【发布时间】:2019-08-09 14:14:17
【问题描述】:

我在 CentOS 7 系统 (perl-5.16) 上使用 PDF::API2 Perl 模块的应用程序中遇到了一个奇怪的问题。每当它尝试使用openpage() 函数时,它都会得到:

Can't call method "inflate" on an undefined value at /usr/share/perl5/vendor_perl/PDF/API2/Basic/PDF/Filter/FlateDecode.pm line 49.

我尝试使用对PDF::API2 的简单调用来重现该问题,但无法触发错误:

#!/usr/bin/perl

use strict;
use warnings;
use PDF::API2;

print "Content-Type: application/pdf\n\n";

my $pdf = PDF::API2->open('/tmp/test.pdf');

my $page = $pdf->openpage(1);

print $pdf->stringify();

接下来,我在我的简单脚本中使用了应用程序自己的高级调用,并且能够触发问题。好吧,我决定使用 Perl 调试器来查找任何差异,并最终在 Zlib 的 deflateInit 子例程 (/usr/share/perl5/Compress/Zlib.pm) 中,尤其是在 Compress::Raw::Zlib::_deflateInit 中:

my $obj ;

my $status = 0 ;
($obj, $status) = 
  Compress::Raw::Zlib::_deflateInit(0,
            $got->getValue('level'), 
            $got->getValue('method'), 
            $got->getValue('windowbits'), 
            $got->getValue('memlevel'), 
            $got->getValue('strategy'), 
            $got->getValue('bufsize'),
            $got->getValue('dictionary')) ;

my $x = ($status == Z_OK() ? bless $obj, "Zlib::OldDeflate"  : undef) ;

据我了解,这是对 zlib C 库的低级调用。在这里,当我使用应用程序的高级调用时,我发现由于“流错误”$status 而没有创建对象。虽然,在这两种情况下,传递的参数(级别、方法等)是完全一样的。我无法在 Compress::Raw::Zlib::_deflateInit 中进一步使用 Perl 调试器,所以它现在对我来说是一个黑盒子。

我坚信该应用程序改变了 Perl 行为的某些方面,但我找不到任何东西。我发现当第一个参数是 NULL(在 C 上下文中)或传递的级别无效值时,会返回“流错误”。我确信级别是正确的,并且在两种情况下(成功和失败)实际上都是相同的。接下来,我想到了第一个参数,它是零(0)。

应用程序是否可能更改 Perl 中的某些内容,从而以不同的方式处理传递的 0(零)参数?如何在Compress::Raw::Zlib::_deflateInit 内部进一步调试问题?

更新:

我继续使用gdb 调试Compress::Raw::Zlib::_deflateInit 调用的C 代码,发现/usr/lib64/perl5/vendor_perl/auto/Compress/Raw/Zlib/Zlib.so/usr/lib64/mysql/libmysqlclient.so.18.1.0 库而不是/usr/lib64/libz.so.1.2.7 调用deflateReset 函数。

现在很清楚为什么我的测试代码无法触发错误,它没有使用 MySQL 函数。但是,应用程序中的代码在 PDF::API2 函数之前使用了大量 MySQL 调用。

我使用从官方存储库安装的 MySQL 社区服务器:

$ rpm -qa | grep mysql
mysql-community-libs-5.6.43-2.el7.x86_64
mysql-community-server-5.6.43-2.el7.x86_64
mysql80-community-release-el7-2.noarch
mysql-community-common-5.6.43-2.el7.x86_64
mysql-community-client-5.6.43-2.el7.x86_64

现在我有新问题了。 MySQL 社区是否错误地将 Zlib 代码捆绑到 libmysqlclient.so 中?作为系统管理员,我可以做些什么来解决问题?谢谢。

【问题讨论】:

  • 也许您安装了多个 Perl 或 Compress::Raw::Zlib 并且您的测试代码和应用程​​序使用不同的版本?顺便说一句:C NULL 通常定义为 (void *) 0,即将 0 作为指针参数传递给 C API 将等效于 NULL
  • 不,我不知道。我使用最小的 CentOS 环境和系统提供的 Perl 5.16。 # grep -FRIn 'package Compress::Raw::Zlib' /usr/ /usr/lib64/perl5/vendor_perl/Compress/Raw/Zlib.pm:2:package Compress::Raw::Zlib; # rpm -qa | grep -i zlib perl-Compress-Raw-Zlib-2.061-4.el7.x86_64 zlib-1.2.7-18.el7.x86_64

标签: mysql perl zlib


【解决方案1】:

好吧,经过几天的调试,很明显核心问题出在 MySQL 社区服务器提供的 libmysqlclient.so 库中。该库与zlib 静态链接,并在全球范围内导出所有zlib 符号。因此,任何同时加载了zlib.solibmysqlclient.so 的二进制文件都有机会从libmysqlclient.so 而不是zlib.so 调用zlib 函数。

相关的bug report 现已打开并获得批准(不幸的是,作为功能请求)。

当我解决问题时,我从 Red Hat Software Collections 切换到 MariaDB 10.2。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-27
    • 2022-07-18
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    • 2019-07-25
    相关资源
    最近更新 更多