HTML::Masonではmasonコンポーネント内でのグローバルをHandlerオブジェクト、もしくはInterpオブジェクト内で作るにはallow_globals引数で指定できるのだがここでApache::Sessionを使うときにちょっと問題:
my $ah = HTML::Mason::ApacheHandler->new(
...
allow_globals => [ qw($session) ]
);my $wrapper = Apache::Session::Wrapper->new(...);
my $session = $wrapper->session;$HTML::Mason::Commands::session = $session;
・・・とやれば普通にできるように思えるが、ところがどっこい。mod_perl内でこれをやると必ずデッドロックにおちいります。なんでじゃーーーと考えに考えてたら昔同じ事でMasonを使うのを諦めた記憶があったのでこりゃこのまま放っておいてはあかんと思い今度こそ問題を見つけてやると思って考える事3時間、よーやくわかったわかった。
問題はただただこのグローバル変数$HTML::Mason::Commands::session。こいつは次回のアクセス時にもまだ生きているのだ。だからそこに新たなセッションオブジェクトを設定すると裏方でDESTROY()が動作するのだが、ここでクリーンアップをしようとする古いApache::Sessionとすでにロックを持っているApache::Sessionがデッドロックになるのだな。
ということはどこかでundefをいれてやればいい:
undef $HTML::Mason::Commands::session;
これ、どこで入れてもいいんだけど多分このコードブロックの最初に入れるのが吉ではないかと思う。普通のプロセスを考えると全く逆なのだが、「クリーンアップは先にやるべき」という考え方もあるのだ。処理の後にクリーンアップを行う場合、エラー等によってクリーンアップのコードが実行されない可能性もある。ところがクリーンアップを最初に行うとコードが実行されない、という可能性が低くなる。しかもmod_perlのようにステートが保持される環境の場合は特に安定性/可用性が高くなるはず。
というわけで問題解決。