1.9.2.0'da Varien_Image_Adapter_Gd2'nin yeni yıkıcısı ile ImportExport sorunu


23

Birisi açıklayabilir mi, Magento CE 1.9.1.0 ve 1.9.2.0 arasında aşağıdaki Kodun neyin kullanıldığını açıklayabilir?

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

Bu iki işlev eklendikten sonra, ImportExport arayüzü olan ürün galerisi resimlerinin içe aktarılması çalışmayı durdurdu. Hata, bir hafıza limitinden kaynaklanmaktadır (bu, maksimum açık dosya boyutu sınırıdır).

Benim fikrim, içe aktarma tarafından açılan dosyaların doğru kapatılmamasıdır.

Ayrıca bazı boş destruct()fonksiyonların ortaya çıktığını gördüm ( Mage_ImportExport_Model_Import_Adapter_Abstract) - ama bunları ana mantığa uyacak şekilde genişletmek yardımcı olmaz.

Yanıtlar:


14

Bu görüntü kaynağını yok etmeye çalıştığından emin görünüyorlar, ancak bunun yerine bir bellek sızıntısı yarattılar. Dürüst olmak gerekirse bu kodun geçerli bir nedenini düşünemiyorum, ancak neyin değiştiğini açıklayabilirim:

Başlangıçta, imagedestroy()inşada aranacaktı__destruct()

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

PHP çöp toplayıcısı kullanılmayan nesneleri (yani artık referans alınmayan bellekteki nesneler) tahrip ettiğinde yıkıcı çağrılır.

Şimdi, imagedestroy()bunun yerine bir kapatma işlevinde çağrılır ve bu, Varien_Image_Adapter_Gd2nesnenin bir yönteminin geri çağrısı olduğu için , sonuna kadar toplanan çöp bile olamaz. Bu şekilde, tüm resim kaynakları script yürütme işlemi tamamlanıncaya kadar açık kalır.


Açıklama için teşekkürler - düşündüğüm şey bu. Bu nedenle genel olarak, bu tanıtılan kod, ithalatların çoğunluğunu 1.9.2'de gereksiz kılmaktadır. gözlerimin içinde. Umarım bu yakında çözülecek. Bug raporunu nerede açacağını bilen var mı?
Achim Rosenhagen

6

Magento 1.9.2.0 ile aynı sorunları yaşıyorsanız ...

Sadece değiştirerek işe bu olsun Varien_Image_Adapter_Gd2 içinde /lib/Varien/Image/Adapter/Gd2.phpaşağıdaki gibi:

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 ile satırı kaldır (veya yorum yapın)
  • değişim işlev adı imha etmek __destruct

Memory_limit'i 1G'ye ayarlamıştım (daha önce 32GB'a yükselttim) ve şimdi çalışıyor ...

Bu proje, söz konusu prosedürü modman dostu bir şekilde uygulamaktadır. Sadece besteci ile yükleyin ve gitmek iyisiniz.


Bu soruya gerçekten cevap vermiyor. Farklı bir sorunuz varsa, Soru Sor'u tıklatarak bunu sorabilirsiniz . Ayrıca , yeterli ününüz olduğunda bu soruya daha fazla dikkat çekmek için bir ödül de ekleyebilirsiniz .
Rajeev K Tomy

Evet, bu soruyu cevaplamıyor, ancak geçici bir çözüme ve tartışmaya ihtiyacı olan insanlara yardım edecek
dkr

içe aktarma sırasında hafıza kullanımıyla ilgili bir sorunu çözdü. İlginç, Magento bir şekilde ne yayınladıklarını test ediyor mu?
klipach

Bu sadece ithalat problemini çözmez. Bu, her ürün görüntüsü için önbellek oluşturma / yeniden oluşturma ve yeniden boyutlandırılmış sürümleri oluşturma işlemiyle büyük bir hafızayı yiyor. Ürünlerime png görüntüleri yüklersem, bu "hack" olmadan çalışamıyorum ve çok fazla bellek tükenmiş hatayı alıyorum.
Simbus82

Bugün bu öneriyi buldum. Uyguladım ve bellek sızıntısı gitti. Sonra temiz bir şekilde kurmak için bu github.com/borasocom-team/magento-gd2-memoryleak'i yarattım .
Dr. Gianluigi Zane Zanettini

5

Seri hale getirme ile güvenlik sorunlarını çözmenin bir parçasıydı. __Destruct gibi sihirli yöntemler seri hale getirme ile ilgili doğal sorunlara sahiptir.

Dosya sisteminde dosya oluşturmak için serileştirme ve __drrucruct kullanan teklifleri gördük - bu değişiklik (diğer yerlerde daha fazla benzer değişiklik göreceksiniz) bunu önlemek için yapıldı.

Bellek sızıntısına neden oluyor mu veya sadece komut dosyası tamamlanana kadar daha fazla bellek kullanıyor mu?

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


Bağlam için teşekkürler. Bu belirli bir istismarın önlenmesi veya sadece emin olmak için yapılan belirli bir değişiklik yapıldı mı?
Fabian Schmengler

Ve hayır, muhtemelen sadece komut değil, gerçek bir bellek sızıntısı daha fazla bellek tüketir hale getirir
Fabian Schmengler

Özellikle görüntüleri alırken, tüm görüntü dosyalarını içe aktarma işleminin sonuna kadar açık tutacağından, büyük bir bellek sızıntısına neden olur. Bu yolla sadece yaklaşık 50 ürün ithal edebiliyoruz (görünüşe göre> 2k ithalat yapmadan önce). Testimi yerel bir VM'de 8G RAM ile yaptım ve kaynak dosyalar yaklaşık 300KB. Değişimden önce, kullanılan bellek PHP tarafından tüm ithalat sırasında 1k'de tekrar çalıştırılır.
Achim Rosenhagen

fschmengler haklı - bir 'bellek sızıntısı' olmayabilir, ancak tüketim tepeye doğru yükselir ;-)
Achim Rosenhagen 24:15

1
Tavsiye için @Alex teşekkürler. Yamayı ters çevirdim. Şimdi, bellek sızıntısı gitti, ancak gelecek için çözüm yok.
Arne

4

Bu yüzden, Magento ile görüntü içe aktarma işleminde bellek kullanımı ile ilgili başa çıkması gereken bir "çözüm" içeren bir hata yaptım.

Çözüm, github'da https://github.com/sitewards/import_image_memory_leak_fix altında bulunabilir fakat temel fikir.

Görüntü işlemci üzerinde Mage_Catalog_Helper_Image::validateUploadFileaslında destructyöntemi çağırmak için Fix . Ne yazık ki, varsayılanın Varien_Imageüstesinden gelmediği anlaşılıyor, bu destructyüzden kendi sınıfımızı eklemek zorunda kaldık.

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

Ve sonra yardımcının tekrar yazması.

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

Ve yeni fonksiyon yeni tahrip edilebilir görüntü sınıfını çağırıyor.

<?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;
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.