Problema ImportExport con il nuovo distruttore di Varien_Image_Adapter_Gd2 in 1.9.2.0


23

Qualcuno può spiegare a cosa serve il seguente codice introdotto tra Magento CE 1.9.1.0 e 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);
}

Dopo aver aggiunto queste due funzioni, la nostra importazione di immagini della galleria di prodotti con l'interfaccia ImportExport ha smesso di funzionare. L'errore è dovuto a un limite di memoria (che risulta essere il limite massimo di dimensione del file aperto).

La mia idea è che i file aperti dall'importazione non vengano chiusi correttamente.

Ho anche visto che sono state destruct()introdotte alcune funzioni vuote ( Mage_ImportExport_Model_Import_Adapter_Abstract) - ma l'estensione di quelle corrispondenti alla logica principale non aiuta.

Risposte:


14

Sembra che abbiano provato a distruggere la risorsa immagine, ma invece hanno introdotto una perdita di memoria. Non posso pensare a un motivo valido per questo codice, ad essere onesti, ma posso spiegare cosa è stato modificato:

In origine, imagedestroy()sarebbe stato chiamato nel descrittore__destruct()

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

Il distruttore viene chiamato ogni volta che il garbage collector di PHP distrugge oggetti inutilizzati (ovvero oggetti in memoria a cui non viene più fatto riferimento).

Ora, imagedestroy()invece , viene chiamato in una funzione di arresto e poiché si tratta di una richiamata a un metodo Varien_Image_Adapter_Gd2dell'oggetto, non può nemmeno essere garbage collection fino alla fine. In questo modo tutte le risorse di immagine rimangono aperte fino al termine dell'esecuzione dello script.


Grazie per la spiegazione - questo è quello che ho pensato. Quindi, nel complesso, questo codice introdotto rende inutile la maggior parte delle importazioni in 1.9.2. nei miei occhi. Spero che questo verrà risolto presto. Qualche consiglio su dove aprire una segnalazione di bug?
Achim Rosenhagen,

6

Ho gli stessi problemi con il mio Magento 1.9.2.0 ...

Ho solo questo per il lavoro modificando Varien_Image_Adapter_Gd2 nel /lib/Varien/Image/Adapter/Gd2.phpmodo seguente:

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

/**
 * Destroy object image on shutdown
 */
public function __destruct()
{
    @imagedestroy($this->_imageHandler);
}
  • rimuovi la riga con register_shutdown_function (o commenta)
  • cambia il nome della funzione destruct in __destruct

Ho reimpostato memory_limit su 1G (in precedenza ho sollevato fino a 32 GB) e ora funziona ...

Questo progetto implementa tale procedura in modo amichevole modman. Basta installarlo con il compositore e sei a posto.


Questo non risponde davvero alla domanda. Se hai una domanda diversa, puoi farla facendo clic su Poni domanda . Puoi anche aggiungere una taglia per attirare più attenzione a questa domanda una volta che hai abbastanza reputazione .
Rajeev K Tomy,

Sì, questo non risponde alla domanda ma aiuterà le persone che hanno bisogno di una soluzione temporanea e nessuna discussione
dkr

risolto un problema con il consumo di memoria durante l'importazione. Interessante, Magento prova in qualche modo ciò che stanno rilasciando?
Klipach,

Questo risolve non solo il problema di importazione. Ciò risolve una grande memoria che si nutre del processo che crea / ricrea la cache e le versioni ridimensionate per ogni immagine dei prodotti. Se carico immagini png nei miei prodotti, senza questo "hack" non riesco a lavorare e ottengo un sacco di errori di memoria esaurita.
Simbus82,

Oggi ho trovato questo suggerimento. L'ho implementato e la perdita di memoria è sparita. Quindi ho creato questo github.com/borasocom-team/magento-gd2-memoryleak per installarlo in modo pulito.
Dr. Gianluigi Zane Zanettini,

5

Faceva parte della risoluzione dei problemi di sicurezza con unserialize. Metodi magici come __destruct hanno problemi inerenti alla serializzazione.

Abbiamo visto exploit proposti che utilizzavano la serializzazione e __destruct per creare file nel file system - e questa modifica (vedrai cambiamenti più simili in altri luoghi) è stata fatta per evitarlo.

Causa perdita di memoria o utilizza solo più memoria fino al termine dello script?

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


Grazie per il contesto. Questo particolare cambiamento è stato fatto per prevenire un exploit specifico o per essere sicuro?
Fabian Schmengler,

E no, probabilmente fa solo consumare più memoria alla sceneggiatura, non una vera perdita di memoria
Fabian Schmengler,

Causa un'enorme perdita di memoria soprattutto durante l'importazione delle immagini, poiché manterrà tutti i file di immagine aperti fino alla fine dell'elaborazione dell'importazione. In questo modo possiamo importare solo circa 50 prodotti (dove prima possiamo fare un'importazione di> 2k apparentemente). Ho eseguito il test su una VM locale con 8G RAM e i file di origine sono tutti circa 300 KB. Prima della modifica, la memoria utilizzata da PHP ritorna a 1k durante l'intera importazione.
Achim Rosenhagen,

fschmengler ha ragione: potrebbe non essere una "perdita di memoria" ma il consumo sale su per la collina ;-)
Achim Rosenhagen,

1
@Alex grazie per il consiglio. L'ho rovesciato. Ora, la perdita di memoria è sparita, ma nessuna soluzione per il futuro.
Arne,

4

Quindi ho sollevato un bug con Magento che includeva una "soluzione" che dovrebbe gestire i problemi di utilizzo della memoria nel processo di importazione delle immagini.

La soluzione è disponibile su github alla pagina https://github.com/sitewards/import_image_memory_leak_fix ma l'idea di base è.

Risolto il problema Mage_Catalog_Helper_Image::validateUploadFileper chiamare effettivamente il destructmetodo sul processore di immagini. Purtroppo sembra che il default Varien_Imagenon abbia a che fare con un destructquindi abbiamo dovuto aggiungere la nostra classe che lo fa.

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

E poi una riscrittura dell'helper.

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

E la nuova funzione chiama la nuova classe di immagini distruttibili.

<?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;
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.