RE:RE:RE: Perl5 の signal 処理と DBI と Q4M

kazuhooku さんにコメント頂いてしまい、恐縮っす。

この件、kazuhooku さんのおっしゃることは理解できたと思う。

kazuhooku さんの元記事はこれ。
Re: Perl5 の signal 処理と DBI と Q4M - kazuhoのメモ置き場



まず、現象はこう。

シグナルハンドラをセットしていると、シグナルを受け取ったときに、ハンドラで指定した所定の処理を実行させることが出来る。しかし、DBI 一般の話として、SQL 実行中はシグナルの処理がブロックされる。(無視されるのではなく、抜けてきてから実行されることになる)これは、XS (で書かれているDBD) で書かれている処理の実行中はシグナルの処理がブロックされているため。(という理解でいいのかな?)

数十秒返ってこないような SQL が無い訳ではないが、通常そういうのは改善の対象になるため、あんまり意識されることはないように思う。しかし、Q4m の場合、queue_wait() は、指定した秒数だけ待つという仕様のため、60 秒返って来ないような SQL を簡単に書けてしまう。

そういう場合でなくても、誤って返って来ないような SQLスクリプト中から投げてしまうことだってある。

となると、例えば、シグナルハンドラをセットしているスクリプト中で返って来ないような SQL を投げてしまった場合、KILL シグナルを送信することでしか終了できなくなってしまうわけである。これはあんまりだよね、と。


で、kazuhooku さんの提案する、この問題に対する回避策はこう。

他のところでシグナルハンドラをセットしているならシグナルハンドラをデフォルト ('DEFAULT') に戻してください。

Re: Perl5 の signal 処理と DBI と Q4M - kazuhoのメモ置き場

シグナルハンドラをセットしていると、XS で書かれている処理の実行中はシグナルの処理がブロックされるようになるけど、逆に言えば、呼び出し前に一旦、DEFAULT に戻せば、即座に INT シグナルを受け取って処理(DEFAULT の振る舞いは即終了)が行なわれるわけである。

この対処で良いとする理由はこう。

queue_wait() を呼んでいる間って他のことは何もしてないんだから、シグナルハンドラセットする必要ないよね、というのが基本的な考え方です。

Re: Perl5 の signal 処理と DBI と Q4M - kazuhoのメモ置き場


で、よく考えると「返ってこないような SQL」を投げてしまうようなことはどうしたって起こりえるわけで、その前提に立って考えるとこれはもうこうするしかないのかもしれない。


しかしそれでも私が嫌がったのは、シグナルハンドラの中で、終了時処理を書いているから。終了時処理では終了ログみたいなものも吐いていたりするので、KILL シグナルを受けたときはともかく、INT シグナルを受けた時にはログは吐いてほしい、と。

で、私は、「そんな長い SQL は投げない。」という対処をしちゃったわけである。具体的には queue_wait() の待ち時間を 2 秒にした、と。ただこれ厳密に言えば、そのように設定したってなんかの問題で永遠に返って来なくなる可能性はあるわけで、KILL シグナル送信で即終了出来るとはいえ、ヌケのある対処といえる。


悩ましいのは、基本的に Q4m を使うようなスクリプトというのは、大体の場合以下の2点の特徴を持っているんではないか?ということ。

・起動しっぱなしで、TERM シグナルか、INT シグナルを受け取って終了するという仕組みをとっている
実行中は大半の時間、queue_wait() を実行中である


queue_wait() を呼ぶ前に INT シグナルハンドラを DEFAULT に戻す、という実装をしたスクリプトを終了させると大体の場合はシグナルハンドラがセットされていない状態になってしまうのだ。終了時処理で終了ログを吐いているような場合、これではつらい。で、私の対処としては、上記のような「永遠に返って来ない可能性」には目をつぶって、queue_wait() の待ち時間を 2 秒にしたわけである。まあ、あちらを立てればこちらが立たず、な問題な気がする。


解決策として一個あるのはもういっそのこと、INT、TERM シグナルは全くハンドルしない、ということだろう。正常終了させたいときは、別のシグナル、例えば、USR1 シグナル等で終了させるような作りにするのだ*1。シグナルの送信自体は xxctrl みたいなプロセスにシグナルを送るためのスクリプトを介するだろうから、利用者に実際投げるシグナルを意識させることは無いはずだし。

*1:USR1, USR2 シグナルは自由な用途に使っていいことになっている