ImportExport Problem mit neuem Destruktor von Varien_Image_Adapter_Gd2 in 1.9.2.0

23

Kann jemand erklären, wofür der folgende zwischen Magento CE 1.9.1.0 und 1.9.2.0 eingeführte Code verwendet wird?

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

Nachdem diese beiden Funktionen hinzugefügt wurden, funktionierte unser Import von Produktgalerie-Bildern mit der ImportExport-Oberfläche nicht mehr. Der Fehler ist auf ein Speicherlimit zurückzuführen (das die maximale Größe der geöffneten Datei angibt).

Meine Idee ist, dass die durch den Import geöffneten Dateien nicht korrekt geschlossen werden.

Ich habe auch gesehen, dass einige leere destruct()Funktionen eingeführt wurden ( Mage_ImportExport_Model_Import_Adapter_Abstract) - aber es hilft nichts, diese so zu erweitern, dass sie mit der übergeordneten Logik übereinstimmen.

Achim Rosenhagen
quelle

Antworten:

14

Es sieht so aus, als hätten sie versucht, die Image-Ressource zu zerstören, aber stattdessen einen Speicherverlust verursacht. Ich kann mir ehrlich gesagt keinen gültigen Grund für diesen Code vorstellen, aber ich kann erklären, was sich geändert hat:

Ursprünglich imagedestroy()wäre im Desktruktor aufgerufen worden__destruct()

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

Der Destruktor wird aufgerufen, wenn der PHP-Garbage-Collector nicht verwendete Objekte (dh Objekte im Speicher, auf die nicht mehr verwiesen wird) zerstört.

Jetzt imagedestroy()wird stattdessen in einer Shutdown-Funktion aufgerufen, und da dies ein Rückruf auf eine Methode des Varien_Image_Adapter_Gd2Objekts ist, kann nicht einmal bis zum Ende Müll gesammelt werden. Auf diese Weise bleiben alle Bildressourcen geöffnet, bis die Skriptausführung abgeschlossen ist.

Fabian Schmengler
quelle
Danke für die Erklärung - daran habe ich gedacht. Insgesamt macht dieser eingeführte Code die Mehrheit der Importe in 1.9.2 unbrauchbar. in meinen Augen. Hoffe, das wird bald behoben. Irgendwelche Ratschläge, wo man einen Fehlerbericht öffnet?
Achim Rosenhagen
6

Ich habe die gleichen Probleme mit meinem Magento 1.9.2.0 ...

Ich erhalte nur diese an der Arbeit , indem Varien_Image_Adapter_Gd2 in /lib/Varien/Image/Adapter/Gd2.phpwie folgt:

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

/**
 * Destroy object image on shutdown
 */
public function __destruct()
{
    @imagedestroy($this->_imageHandler);
}
  • Zeile mit register_shutdown_function entfernen (oder auskommentieren)
  • Ändern Sie den Funktionsnamen destruct in __destruct

Ich habe memory_limit auf 1G zurückgesetzt (vorher habe ich auf 32GB erhöht) und jetzt funktioniert es ...

Dieses Projekt implementiert dieses Verfahren auf eine modmanfreundliche Weise. Einfach mit Composer installieren und los geht's.

dkr
quelle
Dies beantwortet die Frage nicht wirklich. Wenn Sie eine andere Frage haben, können Sie sie stellen, indem Sie auf Frage stellen klicken . Sie können auch ein Kopfgeld hinzufügen, um mehr Aufmerksamkeit auf diese Frage zu lenken, sobald Sie über einen ausreichenden Ruf verfügen .
Rajeev K Tomy
Ja, dies beantwortet nicht die Frage, sondern hilft Menschen, die eine vorübergehende Lösung und keine Diskussion
benötigen
Behebung eines Problems mit dem Speicherverbrauch beim Import. Interessant, testet Magento irgendwie, was sie veröffentlichen?
Klipach
Damit ist nicht nur das Importproblem gelöst. Dies löst einen großen Speicherbedarf durch den Prozess, der den Cache erstellt / neu erstellt und die Versionen für jedes Produktbild verkleinert. Wenn ich PNG-Bilder in meine Produkte hochlade, kann ich ohne diesen "Hack" nicht arbeiten und bekomme eine Menge Speicher voll Fehler.
Simbus82
Heute habe ich diesen Vorschlag gefunden. Ich habe es implementiert und das Speicherleck ist weg. Dann habe ich dieses github.com/borasocom-team/magento-gd2-memoryleak erstellt , um es sauber zu installieren.
Dr. Gianluigi Zane Zanettini
5

Dies war Teil der Behebung von Sicherheitsproblemen mit unseremialize. Magische Methoden wie __destruct haben Probleme mit der Serialisierung.

Es wurden Exploits vorgeschlagen, die Serialisierung und __destruct zum Erstellen von Dateien im Dateisystem verwendeten. Diese Änderung (Sie werden ähnliche Änderungen an anderen Stellen sehen) wurde vorgenommen, um dies zu vermeiden.

Verursacht es einen Speicherverlust oder verbraucht es einfach mehr Speicher, bis das Skript beendet ist?

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

Piotr Kaminski
quelle
Danke für den Zusammenhang. Wurde diese spezielle Änderung vorgenommen, um einen bestimmten Exploit zu verhindern oder nur um sicherzugehen?
Fabian Schmengler
Und nein, das Skript verbraucht wahrscheinlich nur mehr Speicher, kein wirklicher Speicherleck
Fabian Schmengler
Dies führt insbesondere beim Importieren von Bildern zu einem großen Speicherverlust, da alle Bilddateien bis zum Ende der Importverarbeitung geöffnet bleiben. Auf diese Weise können wir nur ca. 50 Produkte importieren (wohingegen wir einen Import von> 2k scheinbar nicht durchführen können). Ich habe meinen Test auf einer lokalen VM mit 8 GB RAM durchgeführt und die Quelldateien sind alle ca. 300 KB groß. Vor der Änderung bleibt der von PHP verwendete Speicher während des gesamten Imports bei 1k.
Achim Rosenhagen
fschmengler hat recht - es ist vielleicht kein "Speicherleck", aber der Verbrauch steigt um ein Vielfaches ;-)
Achim Rosenhagen
1
@Alex danke für den Rat. Ich habe es umgekehrt gepatcht. Jetzt ist Speicherleck weg, aber keine Lösung für die Zukunft.
Arne
4

Also habe ich einen Fehler mit Magento gemeldet, der eine "Lösung" enthielt, die die Probleme mit der Speichernutzung beim Import von Bildern beheben sollte.

Die Lösung finden Sie auf github unter https://github.com/sitewards/import_image_memory_leak_fix, aber die Grundidee ist.

Behebung des Problems Mage_Catalog_Helper_Image::validateUploadFile, die destructMethode tatsächlich auf dem Bildprozessor aufzurufen . Leider scheint es, dass die Standardeinstellung Varien_Imagenicht mit einer übereinstimmt, so dass destructwir unsere eigene Klasse hinzufügen mussten, die dies tut.

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

Und dann eine Umschreibung des Helfers.

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

Und die neue Funktion ruft die neue zerstörbare Bildklasse auf.

<?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;
    }
}
David Manners
quelle