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