SpeedyCGI使ってみた

さっそくハマった。
ハマったとは言ってもmod_perlにもあったような問題で、単にそんなことを忘れていた自分がアホだったという話。


SpeedyCGIを使って自作スクリプトを動かしていたのですが、何か調子が良くない。
よくよく調べてみると、POSTやGETで送るパラメータの値を変えても出力結果が変わらない。
この時はどうしても原因が分からなかったので一旦普通にperlで動かすように戻す。
ググったら三発くらいで原因発覚。
CGIオブジェクトをグローバルスコープでmy付けて宣言して使っていたのだが、それが良くなかった。
SpeedyCGIはPerlスクリプトを走らせたら、コンパイルしたスクリプトPerl自体をメモリ上に保持しておき、次回実行時にはそれを使う。
その結果グローバル変数は内容が引き継がれてしまうのだが、この特徴とmyによる動作によって、サブルーチン内でグローバル変数にアクセスしているとおかしな動作をする。
動作としては、myによる宣言によってグローバル変数は以前とは異なるオブジェクトとして生成されるが、サブルーチンは既にコンパイルされているので、サブルーチン内部でアクセスしているグローバル変数が示すオブジェクトは以前コンパイルされた時のグローバル変数が示していたオブジェクトとなってしまうという事。すごい分かりにくい。
整理するとこんな感じ。

初回実行時(スクリプトのコンパイル発生)
グローバル変数(A) : myがついているので一意な識別子(1)が割り当てられる。
サブルーチン(B) : コンパイルされ、内部に記述されている(A)は(1)へと変換される。

2回目実行時(スクリプトのコンパイルが発生しない)
グローバル変数(A) : myがついているので一意な識別子(2)が割り当てられる。
サブルーチン(B) : 既にコンパイルされているので、内部からアクセスする(A)は実際には(1)。

そりゃ動かないわけだよ。