1.9.2.0中新的Varien_Image_Adapter_Gd2析构函数的ImportExport问题


23

有人可以解释一下,Magento CE 1.9.1.0和1.9.2.0之间引入的以下代码有什么用吗?

class Varien_Image_Adapter_Gd2:

public function __construct()
{
    // Initialize shutdown function
    register_shutdown_function(array($this, 'destruct'));
}

/**
 * Destroy object image on shutdown
 */
public function destruct()
{
    @imagedestroy($this->_imageHandler);
}

添加这两个功能后,我们使用ImportExport接口导入产品库图像的操作停止。该错误是由于内存限制(结果是最大打开文件大小限制)引起的。

我的想法是,导入将无法正确关闭打开的文件。

我还看到destruct()引入了一些空函数(Mage_ImportExport_Model_Import_Adapter_Abstract)-但是扩展这些函数以匹配父级逻辑无济于事。

Answers:


14

看起来他们试图确保销毁图像资源,但却引入了内存泄漏。老实说,我想不出这段代码的正当理由,但是我可以解释一下已更改的内容:

本来imagedestroy()应该在解扰器中调用__destruct()

function __destruct()
{
    @imagedestroy($this->_imageHandler);
}

每当PHP垃圾回收器销毁未使用的对象(即,内存中不再引用的对象)时,就会调用析构函数。

现在,imagedestroy()它在关闭函数中被调用,并且由于这是对Varien_Image_Adapter_Gd2对象方法的回调,因此直到最后都无法进行垃圾回收。这样,所有图像资源将保持打开状态,直到脚本执行完成。


感谢您的解释-这就是我的想法。因此,总的来说,此引入的代码使大多数导入在1.9.2上无用。在我眼里。希望此问题能尽快解决。任何建议在哪里打开错误报告?
Achim Rosenhagen 2015年

6

我的Magento 1.9.2.0遇到相同的问题...

我只能通过改变得到这个工作Varien_Image_Adapter_Gd2/lib/Varien/Image/Adapter/Gd2.php,如下所示:

public function __construct()
{
    // Initialize shutdown function
    // register_shutdown_function(array($this, 'destruct'));
}

/**
 * Destroy object image on shutdown
 */
public function __destruct()
{
    @imagedestroy($this->_imageHandler);
}
  • register_shutdown_function删除行(或注释掉)
  • 将函数名称destruct更改为__destruct

我已将memory_limit设置回1G(以前我提高到了32GB),现在它可以工作了...

该项目以modman友好的方式实现了上述程序。只需在composer上安装它,就可以了。


这并不能真正回答问题。如果您有其他问题,可以点击提问。一旦您拥有足够的声誉,您还可以悬赏以吸引更多对此问题的关注。
拉吉夫K托米2015年

是的,这不能回答问题,但会帮助需要临时解决方案且无需讨论的人们
dkr

解决了导入过程中内存消耗的问题。有趣的是,Magento是否以某种方式测试了它们发布的内容?
klipach '16

这不仅解决了导入问题。通过为每个产品映像创建/重新创建缓存和调整大小的版本的过程,这解决了占用大量内存的问题。如果我在产品中上传png图像,没有此“ hack”,我将无法工作,并且会出现大量内存耗尽错误。
Simbus82年

今天我发现了这个建议。我实现了它,内存泄漏消失了。然后,我创建了这个github.com/borasocom-team/magento-gd2-memoryleak以干净的方式安装它。
Gianluigi Zane Zanettini博士

5

这是通过反序列化解决安全问题的一部分。__destruct之类的魔术方法在序列化方面存在固有的问题。

我们已经看到有人提出利用漏洞利用序列化和__destruct在文件系统中创建文件的漏洞-进行此更改(在其他地方会看到更多类似的更改)是为了避免这种情况。

它是否会导致内存泄漏或只是在脚本完成之前使用更多的内存?

/security/77549/is-php-unserialize-exploitable-without-any-interesting-methods


感谢您提供的上下文。进行此特定更改是为了防止特定漏洞利用还是为了确定?
Fabian Schmengler,2015年

不,这可能只会使脚本消耗更多的内存,而不是真正的内存泄漏
Fabian Schmengler 2015年

这会导致巨大的内存泄漏,尤其是在导入图像时,因为它将保持所有图像文件打开,直到导入处理结束。这样一来,我们只能导入大约50种产品(似乎很难导入> 2k的产品)。我在具有8G RAM的本地VM上进行了测试,源文件均为300KB左右。更改之前,在整个导入过程中,PHP的已用内存保留为1k。
Achim Rosenhagen 2015年

fschmengler是对的-可能不是“内存泄漏”,但是消耗量上升了;-)
Achim Rosenhagen

1
@Alex感谢您的建议。我反向打补丁。现在,内存泄漏消失了,但未来没有解决方案。
Arne 2015年

4

因此,我确实在Magento上提出了一个错误,其中包括一个“解决方案”,该解决方案应处理图像导入过程中的内存使用问题。

该解决方案可以在https://github.com/sitewards/import_image_memory_leak_fix的 github上找到但基本思想是。

修复Mage_Catalog_Helper_Image::validateUploadFile实际destruct在图像处理器上调用该方法的问题。可悲的是,默认值Varien_Image似乎不处理,destruct因此我们不得不添加自己的类。

<?php
/**
 * @category    Sitewards
 * @package     Sitewards_ImportImageMemoryLeakFix
 * @copyright   Copyright (c) Sitewards GmbH (http://www.sitewards.com/)
 */
class Sitewards_ImportImageMemoryLeakFix_Model_Destructable_Image extends Varien_Image
{
    /**
     * Constructor,
     * difference from original constructor - we register a destructor here.
     *
     * @param string $sFileName
     * @param Varien_Image_Adapter $oAdapter Default value is GD2
     */
    public function __construct($sFileName = null, $oAdapter = Varien_Image_Adapter::ADAPTER_GD2)
    {
        parent::__construct($sFileName, $oAdapter);

        // Initialize shutdown function
        register_shutdown_function(array($this, 'destruct'));
    }

    /**
     * Destroy object image on shutdown
     */
    public function destruct()
    {
        $oAdapter = $this->_getAdapter();
        if (method_exists($oAdapter, 'destruct')) {
            $oAdapter->destruct();
        } else {
            Mage::log('Image can not be destructed properly, adapter doesn\'t support the method.');
        }
    }
}

然后重写助手。

<?xml version="1.0"?>
<config>
    <modules>
        <Sitewards_ImportImageMemoryLeakFix>
            <version>0.1.0</version>
        </Sitewards_ImportImageMemoryLeakFix>
    </modules>
    <global>
        <models>
            <sitewards_importimagememoryleakfix>
                <class>Sitewards_ImportImageMemoryLeakFix_Model</class>
            </sitewards_importimagememoryleakfix>
        </models>
        <helpers>
            <catalog>
                <rewrite>
                    <image>Sitewards_ImportImageMemoryLeakFix_Helper_Catalog_Helper_Image</image>
                </rewrite>
            </catalog>
        </helpers>
    </global>
</config>

新函数将调用新的可销毁图像类。

<?php
/**
 * @category    Sitewards
 * @package     Sitewards_ImportImageMemoryLeakFix
 * @copyright   Copyright (c) Sitewards GmbH (http://www.sitewards.com/)
 */
class Sitewards_ImportImageMemoryLeakFix_Helper_Catalog_Helper_Image extends Mage_Catalog_Helper_Image
{
    /**
     * Check - is this file an image
     *
     * Difference from original method - we destroy the image object here,
     * i.e. we are not wasting memory, without that fix product import with images
     * easily goes over 4Gb on memory with just couple hundreds of products.
     *
     * @param string $sFilePath
     *
     * @return bool
     * @throws Mage_Core_Exception
     */
    public function validateUploadFile($sFilePath) {
        if (!getimagesize($sFilePath)) {
            Mage::throwException($this->__('Disallowed file type.'));
        }

        /** @var Sitewards_ImportImageMemoryLeakFix_Model_Destructable_Image $oImageProcessor */
        $oImageProcessor = Mage::getModel('sitewards_importimagememoryleakfix/destructable_image', $sFilePath);
        $sMimeType       = $oImageProcessor->getMimeType();
        $oImageProcessor->destruct();

        return $sMimeType !== null;
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.