Vấn đề ImportExport với hàm hủy mới của Varien_Image_Ad CHƯƠNG_Gd2 trong 1.9.2.0


23

Ai đó có thể giải thích, Mã sau đây được giới thiệu giữa Magento CE 1.9.1.0 và 1.9.2.0 được sử dụng để làm gì không?

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);
}

Sau khi hai chức năng này được thêm vào, quá trình nhập hình ảnh bộ sưu tập sản phẩm của chúng tôi với giao diện ImportExport đã ngừng hoạt động. Lỗi là do giới hạn bộ nhớ (đi ra là giới hạn kích thước tệp mở tối đa).

Ý tưởng của tôi là, các tệp được mở bởi quá trình nhập sẽ không được đóng chính xác.

Tôi cũng thấy rằng có một số destruct()hàm trống được giới thiệu ( Mage_ImportExport_Model_Import_Adapter_Abstract) - nhưng việc mở rộng chúng để phù hợp với logic cha mẹ không giúp ích được gì.

Câu trả lời:


14

Có vẻ như họ đã cố gắng đảm bảo phá hủy tài nguyên hình ảnh, nhưng thay vào đó lại gây ra rò rỉ bộ nhớ. Tôi không thể nghĩ ra một lý do hợp lệ cho mã này, thành thật mà nói, nhưng tôi có thể giải thích những gì đã được thay đổi:

Ban đầu, imagedestroy()sẽ được gọi trong desctructor__destruct()

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

Hàm hủy được gọi bất cứ khi nào trình thu gom rác PHP phá hủy các đối tượng không sử dụng (tức là các đối tượng trong bộ nhớ không được tham chiếu nữa).

Bây giờ, imagedestroy()thay vào đó được gọi trong một chức năng tắt máy và vì đây là một cuộc gọi lại cho một phương thức của Varien_Image_Adapter_Gd2đối tượng, nó thậm chí không thể được thu gom rác cho đến khi kết thúc. Bằng cách này, tất cả các tài nguyên hình ảnh vẫn mở cho đến khi việc thực thi tập lệnh kết thúc.


Cảm ơn đã giải thích - đây là những gì tôi nghĩ. Vì vậy, về tổng thể, mã được giới thiệu này làm cho phần lớn hàng nhập khẩu trở nên vô dụng vào ngày 1.9.2. trong mat toi. Hy vọng điều này sẽ được khắc phục sớm. Bất kỳ tư vấn nơi để mở một báo cáo lỗi?
Achim Rosenhagen

6

Có cùng vấn đề với Magento 1.9.2.0 của tôi ...

Tôi chỉ được điều này để làm việc bằng cách thay đổi Varien_Image_Adapter_Gd2 trong /lib/Varien/Image/Adapter/Gd2.phpnhư sau:

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

/**
 * Destroy object image on shutdown
 */
public function __destruct()
{
    @imagedestroy($this->_imageHandler);
}
  • xóa dòng với register_shutdown_function (hoặc nhận xét)
  • thay đổi hủy tên hàm thành __desturation

Tôi đã đặt memory_limit trở lại 1G (trước đây tôi đã tăng lên 32GB) và bây giờ nó hoạt động ...

Dự án này thực hiện thủ tục cho biết một cách thân thiện modman. Chỉ cần cài đặt nó với nhà soạn nhạc và bạn sẽ ổn.


Điều này không thực sự trả lời câu hỏi. Nếu bạn có một câu hỏi khác, bạn có thể hỏi nó bằng cách nhấp vào Đặt câu hỏi . Bạn cũng có thể thêm tiền thưởng để thu hút sự chú ý hơn cho câu hỏi này một khi bạn có đủ danh tiếng .
Rajeev K Tomy

Vâng, điều này không trả lời câu hỏi nhưng sẽ giúp những người cần một giải pháp tạm thời và không cần thảo luận
dkr

đã khắc phục sự cố với mức tiêu thụ bộ nhớ trong quá trình nhập. Thật thú vị, Magento có kiểm tra bằng cách nào đó những gì họ đang phát hành không?
klipach

Điều này giải quyết không chỉ vấn đề nhập khẩu. Điều này giải quyết việc ăn bộ nhớ lớn theo quy trình tạo / tạo lại bộ đệm và phiên bản thay đổi kích thước cho mỗi hình ảnh sản phẩm. Nếu tôi tải lên hình ảnh png trong các sản phẩm của mình, không có "hack" này, tôi không thể làm việc và tôi nhận được rất nhiều lỗi hết bộ nhớ.
Simbus82

Hôm nay tôi tìm thấy gợi ý này. Tôi thực hiện nó và rò rỉ bộ nhớ đã biến mất. Sau đó, tôi đã tạo github.com/borasocom-team/magento-gd2-memoryleak này để cài đặt nó một cách sạch sẽ.
Bác sĩ Gianluigi Zane Zanettini

5

Đó là một phần của việc khắc phục các vấn đề bảo mật với unserialize. Các phương thức ma thuật như __desturation có vấn đề cố hữu với việc tuần tự hóa.

Chúng tôi đã thấy các khai thác được đề xuất sử dụng tuần tự hóa và __desturation để tạo các tệp trong hệ thống tệp - và thay đổi này (bạn sẽ thấy nhiều thay đổi tương tự ở những nơi khác) đã được thực hiện để tránh điều này.

Nó có gây rò rỉ bộ nhớ hay chỉ sử dụng thêm bộ nhớ cho đến khi tập lệnh kết thúc?

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


Cảm ơn vì bối cảnh. Sự thay đổi cụ thể này đã được thực hiện để ngăn chặn một khai thác cụ thể hay chỉ để chắc chắn?
Fabian Schmengler

Và không, nó có lẽ chỉ làm cho kịch bản tiêu thụ nhiều bộ nhớ hơn, không bị rò rỉ bộ nhớ thực
Fabian Schmengler

Nó gây ra rò rỉ bộ nhớ lớn đặc biệt là khi nhập hình ảnh, vì nó sẽ giữ tất cả các tệp hình ảnh mở cho đến khi kết thúc quá trình nhập. Bằng cách này, chúng tôi chỉ có thể nhập khoảng 50 sản phẩm (trước khi chúng tôi có thể nhập> 2k dường như). Tôi đã chạy thử nghiệm trên máy ảo cục bộ với RAM 8G và các tệp nguồn đều có dung lượng khoảng 300KB. Trước khi thay đổi bộ nhớ đã sử dụng bởi PHP sẽ hiển thị ở mức 1k trong toàn bộ quá trình nhập.
Achim Rosenhagen

fschmengler là đúng - nó có thể không phải là một 'bộ nhớ bị rò rỉ' nhưng mức tiêu thụ tăng lên thraight đồi ;-)
Achim Rosenhagen

1
@Alex cảm ơn đã tư vấn. Tôi đảo ngược vá nó. Bây giờ, rò rỉ bộ nhớ đã biến mất, nhưng không có giải pháp cho tương lai.
Arne

4

Vì vậy, tôi đã đưa ra một lỗi với Magento bao gồm một "giải pháp" giải quyết các vấn đề sử dụng bộ nhớ trong quá trình nhập ảnh.

Giải pháp có thể được tìm thấy trên github trong https://github.com/sitewards/import_image_memory_leak_fix nhưng ý tưởng cơ bản là.

Sửa lỗi Mage_Catalog_Helper_Image::validateUploadFileđể thực sự gọi destructphương thức trên bộ xử lý hình ảnh. Đáng buồn thay, có vẻ như mặc định Varien_Imagekhông xử lý destructvì vậy chúng tôi đã phải thêm lớp riêng của chúng tôi.

<?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.');
        }
    }
}

Và sau đó viết lại của người trợ giúp.

<?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>

Và hàm mới gọi lớp hình ảnh có thể phá hủy mới.

<?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;
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.