05 July 2009

PerlモジュールCrypt::DSA の/dev/randomが原因によるインストール障害

PerlモジュールCrypt::DSAのインストールを、CPANシェル上から行おうとも、コマンドラインから行おうとも、非常に長時間掛かる不具合がある。

分かりやすく説明するために、ソースコードから全て手動でインストールする方法を記載する。

Crypt::DSAのソースパッケージは、http://search.cpan.org/から最新版を取得するものとする。(下記の説明は、適宜最新版のパスに置き換えること)

root@localhost:~/working# wget http://search.cpan.org/CPAN/authors/id/B/BT/BTROTT/Crypt-DSA-0.14.tar.gz root@localhost:~/working# tar xvf Crypt-DSA-0.14.tar.gz root@localhost:~/working# cd Crypt-DSA-0.14 root@localhost:~/working/Crypt-DSA-0.14# perl Makefile.PL Cannot determine perl version info from lib/Crypt/DSA.pm *** Module::AutoInstall version 1.02 *** Checking for Perl dependencies... [Core Features] - Digest::SHA1 ...loaded. (2.12) - Math::BigInt ...loaded. (1.89 >= 1.60) [Read/write PEM-encoded files] - Convert::PEM ...loaded. (0.07 >= 0.07) [Read/write SSH2 keyfiles] - Data::Buffer ...loaded. (0.04 >= 0.01) *** Module::AutoInstall configuration finished. Writing Makefile for Crypt::DSA root@localhost:~/working/Crypt-DSA-0.14# make Manifying blib/man3/Crypt::DSA::Key::SSH2.3pm Manifying blib/man3/Crypt::DSA::Signature.3pm Manifying blib/man3/Crypt::DSA.3pm Manifying blib/man3/Crypt::DSA::Util.3pm Manifying blib/man3/Crypt::DSA::KeyChain.3pm Manifying blib/man3/Crypt::DSA::Key::PEM.3pm Manifying blib/man3/Crypt::DSA::Key.3pm root@localhost:~/working/Crypt-DSA-0.14# make test ~省略~ ath::BigInt: couldn't load specified math lib(s), fallback to Math::BigInt::FastCalc at /root/working/Crypt-DSA-0.14/blib/lib/Crypt/DSA/Key.pm line 6 Math::BigInt: couldn't load specified math lib(s), fallback to Math::BigInt::FastCalc at /root/working/Crypt-DSA-0.14/blib/lib/Crypt/DSA/Util.pm line 6 Name "Crypt::DSA::KeyChain::NULL" used only once: possible typo at /root/working/Crypt-DSA-0.14/blib/lib/Crypt/DSA/KeyChain.pm line 40. ← ここで恐ろしく時間が掛かる

時間が掛かるというものではなく、make test 完了まで数時間待ってもぜんぜん終わらない雰囲気。 私の予想では数日以上掛かるのでは… (笑

Googleでいろいろ検索すると、ここで時間が掛かる(フリーズしているように見える)のは、多くのサーバ管理者などでも同じ経験をしているようだ。書かれている解決策は、足りない依存パッケージを追加したとか、make testをすっ飛ばしてmake installしたとか、どれも根本的な解決ではないものばかり。

で、とりあえず足りない依存パッケージが無いか、CPANのCrypt::DSAページに記されている依存関係の各ファイルをCPANでインストールしてみる。

 ・Digest::SHA1
 ・Digest::base
 ・Math::BigInt

blib/lib/Crypt ディレクトリ以下にある DSA.pm, Key.pm, Util.pm, KeyChain.pm, Util.pm などのソースコードを眺めてみて、use宣言されている外部依存パッケージも、念のためにCPANでインストールされていることを確認する。

ここまで行っても、問題は解決しない。原因は依存関係のモジュールが無いのではなく、別のところにある

Google検索で意味深長なブログ「/dev/randomと/dev/urandom」を発見。

乱数発生の部分を grep ./* -r -e "\/dev\/random" で見つけ出す。1箇所発見された。 そこに対策を施すことにする。

blib/lib/Crypt/DSA/Util.pm
~ 省略 ~ sub makerandom { my %param = @_; my $size = $param{Size}; my $bytes = int($size / 8) + 1; my $r = ''; # if ( sysopen my $fh, '/dev/random', O_RDONLY ) { if ( sysopen my $fh, '/dev/urandom', O_RDONLY ) {← このように書き換え my $read = 0; ~ 省略 ~

おそらく、乱数発生に/dev/randomを利用しているので、ループで何度も呼び出されるときにブロックされまくって、無限大の時間が掛かるのだろう。
安全性は下がるが擬似乱数の/dev/urandomを用いることで、人間が我慢できる範囲内の処理時間に押さえ込めるはずだ。

ということで、この変更をすることにより、make test が滞りなく進み (それでも、1分くらい掛かった)、make install まで行うことが出来た。

このモジュールの作者は、どんだけスーパーコンピューターな開発環境で実証してんだ (w