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

これらの2つの機能が追加された後、ImportExportインターフェイスを使用した製品ギャラリー画像のインポートが機能しなくなりました。このエラーは、メモリの制限によるものです(これは、最大オープンファイルサイズ制限になります)。

私の考えは、インポートによって開かれたファイルが正しく閉じられないということです。

また、いくつかの空のdestruct()関数が導入されていることもわかりました(Mage_ImportExport_Model_Import_Adapter_Abstract)-しかし、それらを親ロジックに合わせて拡張しても効果はありません。

回答:


14

画像リソースを確実に破棄しようとしたが、代わりにメモリリークが発生したようです。正直なところ、このコードの正当な理由を考えることはできませんが、何が変更されたかを説明できます。

もともとimagedestroy()は、デストラクターで呼び出されていました__destruct()

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

デストラクタは、PHPガベージコレクタが未使用のオブジェクト(つまり、メモリ内で参照されなくなったオブジェクト)を破棄するたびに呼び出されます。

現在、imagedestroy()代わりにシャットダウン関数で呼び出され、これはVarien_Image_Adapter_Gd2オブジェクトのメソッドへのコールバックであるため、最後までガベージコレクションすることさえできません。これにより、スクリプトの実行が終了するまで、すべての画像リソースが開いたままになります。


説明をありがとう-これは私が考えていたものです。そのため、全体として、この導入されたコードにより、1.9.2ではほとんどのインポートが使用できなくなります。私の目に。これがすぐに修正されることを願っています。バグレポートをどこで開くかアドバイスはありますか?
アヒムローゼンハーゲン

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トミー

はい、これは質問に答えませんが、一時的な解決策が必要で、議論は必要ありません
-dkr

インポート中のメモリ消費の問題を修正しました。興味深いことに、Magentoはリリースするものをなんとかテストしていますか?
クリパチ

これはインポートの問題だけでなく解決します。これにより、すべての製品イメージのキャッシュとサイズ変更されたバージョンを作成/再作成するプロセスによって消費される大きなメモリが解決されます。製品にPNG画像をアップロードすると、この「ハック」なしでは動作せず、メモリ不足のエラーが大量に発生します。
Simbus82

今日、私はこの提案を見つけました。私はそれを実装し、メモリリークはなくなりました。次に、このgithub.com/borasocom-team/magento-gd2-memoryleakを作成して、クリーンな方法でインストールしました。
ジャンルイジゼーンザネッティニ博士

5

これは、シリアル化解除に関するセキュリティ問題の修正の一部でした。__destructなどのマジックメソッドには、シリアル化に固有の問題があります。

シリアル化と__destructを使用してファイルシステムにファイルを作成するエクスプロイトが提案されたことを確認しました-この変更(他の場所でも同様の変更が表示されます)は、これを回避するために行われました。

スクリプトが終了するまで、メモリリークが発生したり、メモリを使用したりしますか?

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


コンテキストをありがとう。この特定の変更は、特定の悪用を防止するために行われたのですか、それとも念のためですか?
ファビアンシュメングラー

いいえ、それはおそらく、スクリプトが実際のメモリリークではなく、より多くのメモリを消費するようになるためです
ファビアンシュメングラー

インポート処理が終了するまで、すべての画像ファイルを開いたままにしておくため、特に画像をインポートするときに、巨大なメモリリークが発生します。この方法では、約50個の製品のみをインポートできます(2kを超えてインポートすることはできません)。8G RAMのローカルVMでテストを実行しましたが、ソースファイルはすべて約300KBです。変更の前に、全体のインポート中にPHPが使用するメモリを1kで使用します。
アヒムローゼンハーゲン

fschmenglerは正しい-それは「メモリリーク」ではないかもしれないが、消費は丘を登って行く;-)
アヒムローゼンハーゲン

1
@Alex、アドバイスをありがとう。私はそれを逆パッチしました。現在、メモリリークはなくなりましたが、将来の解決策はありません。
アルネ

4

そのため、イメージのインポートプロセスでのメモリ使用量の問題に対処する「ソリューション」を含むMagentoのバグを提起しました。

解決策は、githubのhttps://github.com/sitewards/import_image_memory_leak_fixにありますが、基本的な考え方は次のとおりです。

画像プロセッサで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;
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.