Upload
tetsuji-ogata
View
408
Download
0
Embed Size (px)
Citation preview
処理全体の例外を透過的に 捕捉するいくつかの考え
OGATA Tetsuji (@xtetsuji) 2015/01/31 Hachioji.pm#46
自己紹介
• 尾形 鉄次 (OGATA Tetsuji)
• Twitter: @xtetsuji
• Blog: http://post.tetsuji.jp/
• 今年もよろしくお願いします。いろいろやります。
• 現在無職です
2015年1月31日
1年前の2014年1月31日に 株式会社fonfunを退職
そして色々事情があって 次の会社も退職
そして無職
できた時間で、療養と いくつかの活動を進行中
思索がはかどる
fonfun時代の最後の上司のコードテンプレを思い出した
#!/usr/bin/perluse strict;use warnings;use Project::CGI;...;{ ## 無名ブロック始まりmy $cgi = new Project::CGI;my $rv = eval { ...; # 一般的な処理};if( $@ || !defined $rv ) { ...; # 例外処理}} ## 無名ブロック終わりexit;
このコードテンプレート
• Perl CGIとしてのmod_perlの高速化環境のコード(ModPerl::RegistryPrefork)
• 処理のほとんどを eval { … }; でくくっている
• 処理の最後で例外処理
• ブロックevalの中にブロックevalがあることもあるけれど、続ける場合は $@ に注意するとかはある
ときどき言っていたこと
• 私「このやり方、一つの方法として面白いんですけど、毎回書くのダルくないですか?」
• 上司「ダルいね」
• 私「これモジュールにできそうなものですけれど」
• 上司「別にいいよ」
やり方考えてみた
• スクリプト中にCATCHという関数があれば、スクリプトで例外が発生したときにそいつが呼ばれるといいな
• ENDもsubが要らないだけの特殊サブルーチンだし、CATCH関数の存在もuseしたモジュールから確認することができるから、なんかうまくいきそう
呼び出し側use Try::ProecessCatch;
...;
sub CATCH { my $e = shift; if ( $e ) { ...; }}
モジュール側package Try::ProcessCatch; # 仮
sub import { my ($package) = caller; no strict 'refs'; my $end_cb = ${"$package\::"}{END} || sub {}; # あれば my $catch_cb = ${"$package\::"}{CAHTCH} || sub {}; # 独自 my $new_end_cb = sub { $end_cb->(); $catch_cb->($@); } ${"$package\::"}{END} = $new_end_cb;}
1;
これで
• callerで呼び出し元パッケージ名を取得してシンボルテーブルをいじる
• $@ は真のグローバル変数だからこれでいい
• …はずなんだけどうまくいかない
コンパイル時の順序問題
• use も 関数定義も同じコンパイル時なので、上に書けば当然 use Try::ProcessCatch した段階では END も CATCH も見つけられない
• かといって、use は END や CATCH の下に書いてねっていうのもダサい…
そもそもmod_perlで動かないし• mod_perlでのENDは、HTTPリクエスト処理の終了時ではなく、Apacheのプロセスの終了時だった!
• これは ModPerl::RegistryPrefork を改造するのが早い
• mod_perl2だと、ModPerl::RegistryCooker から簡単に拡張できて美味しい → この実装は大変そうだけど
• 逆にmod_perl2だと順序関係ないし、これでいいのか!
PSGIファイルだと
• 事情は一緒っぽい
• コードのコンパイル部分(サンドボックス作成部分)に介入するのは泥沼化しそう(ここがmod_perlとの違い)
• psgix.harakiriはクリーンナップフェーズだろうし、ちょっと意味合いが違う
• 簡単そうに見えて、意外に難しいのは自分の勉強不足
課題
• コンパイルフェーズで上から下へ解釈されるものの遅延評価みたいなことはできるんだろうか
• ModPerl::ReigstryCooker拡張を頑張る
• Plackのソースコードを理解する
アイデアお待ちしています
おしまい