お知らせ
絶対使わないと言い切れますか? blog + wiki = adiary
▼ 2010/02/22(月) SpeedyCGI で ImageMagick が動かない
Webアプリ開発中に ImageMagick(perlmagick)が SpeedyCGI 環境でまともに動かない不具合に当たりました。
■問題の詳細
- Image::Magick をロードして何かしら処理を行うルーチンを SpeedyCGI で実行する時、2回目以降のキャッシュされた状態で不具合が起こる*1。
- 問題確認環境
- Perl 5.8.8 + SpeedyCGI 2.22
- ImageMagick 6.3.7 および 6.5.9
この問題は FastCGI や mod_perl2 では起きません。
*1 : スクリプトの処理が停止してしまう。もしくは処理中のまま返ってこなくなる
■問題の症状
スクリプト
#!/usr/bin/speedy use Image::Magick(); print "Content-Type: text/plain\n\n"; print "Image::Magick Version $Image::Magick::VERSION \n"; my $image = Image::Magick->new; $image->Read( 'x.png' ); }
実行結果。
~$ test.pl Image::Magick Version 6.3.7 ~$ test.pl Segmentation fault
~$ test.pl Image::Magick Version 6.5.9 ~$ test.pl Segmentation fault
■問題の原因
不明。
■問題の解決法??
ENDブロックを呼ばれないようにして終了時のメモリ開放はOSやPerl自身に任せる。
#!/usr/bin/speedy
use Image::Magick();
sub Image::Magick::END {}
print "Content-Type: text/plain\n\n";
print "Image::Magick Version $Image::Magick::VERSION \n";
my $image = Image::Magick->new;
$image->Read( 'x.png' );
}
たしかにこれで問題は起こらなくなるのですが、
$image->Write( 'x.jpg' );
をするだけでダメになる。とにかくメモリリークっぽい挙動ですが、詳細が不明の挙動不明で、試行錯誤の末 Image::Magick をロードするダミーモジュールを作成しましたが、これで回避できるケースと回避できないケースがあり暗中模索。
- ImageMagick.pm
use strict; package ImageMagick; sub new { require Image::Magick; return Image::Magick->new; } - main.pl
use ImageMagick(); my $img = ImageMagick->new; # # $img は Image::Magick のオブジェクトであるので、 # Image::Magick と同様に利用できる。 #
■まとめ
とりあえず現在のところ挙動が意味不明です。ファイル入出力と関連してバグっている様ですが……。
gccの(ライブラリlibgomp )バグのようです。gcc 4.3より前のVersion(4.2以下)で、amd64環境の時起こる模様。
■メモ
256色png(8bitカラーパレット)で保存する方法。
$image->Read( 'x.png' ); $image->Resize(width=>133, height=>100); $image->Quantize(colorspace=>'RGB',colors=>256); $image->Set(depth => 8); $image->Write( 'y.png' );
- TB-URL http://adiary.blog.abk.nu/0267/tb/
-
▼
ApacheのRLimitMEMが効かない
adiary開発日誌 CGI開発中についうっかり無限ループを生成するなんて経験のある人も多いと思いますが、つい最近2回連続でサーバごと落としてしまったので*1本格的に対策しました。 *1 : メモリオーバーフローでカーネルが端からプロセスを殺し始めてサーバ停止■RLimitME...

1: 竹 2010年03月13日(土) 午後10時55分
ものすごく勘でものを言いますが。
PerlでSQLiteのオブジェクトが解放されない現象に似ているかもしれません。
使い終わった Image:Magick オブジェクトを明示的に delete $image; してみるとどうでしょう?
2: なべ 2010年03月13日(土) 午後11時43分
delete $image; はできないので、undef $image したけど同じですね。
ENDが内部的に呼ばれてるので、オブジェクトの破棄はされてるんですよね。