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)。
そりゃ動かないわけだよ。