[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[FDclone-users:00153] Re: {FreeBSD,OpenBSD}/sparc64, IA64(AIX 対応その後)



潮田@徹夜あけです。
やっぱり長文です。

> >  IBM との保守契約はどうなっています?
> BP(ビジネス・パートナー)向けのリース契約で、ハードに関しては
> 細かく書いてありますが、ソフトに関しては特に書いてないみたい
> です。
> 購入した担当者に確認してみます。
これは、購入時の IBM 側営業マンにメールを投げたので、
結果は後日ということで。
(門前払いの可能性が大ですが)


で、寝付けず Web 上をさまよっていたら
[FDclone-users:00148] で私の書きました
> 私自身、 AIX 上で同じこと(SIGCHLD のハンドラ中で再度 SIGCHLD の
> ハンドラのセット)をしているプログラムを書いていて、それが今も
> 某所で動いています。
> もっと雑なつくりで、どんな signal を捕らえても、すべてのハンドラを
> 再度セットするようなやつですが。
> うーん、なぞ。
の、からくりが少しわかりました。

小島さんのセキュリティホール memo で、 OpenSSH portable の 
version があがったネタを発見。
ふーん、 AIX 名指しなんだとか独り言をいいながらソースを wget 。
で、いつもなら絶対しないのに、これの SIGCHLD のハンドラーはと、
ソースをながめてみました。

> static void
> main_sigchld_handler(int sig)
> {
>         int save_errno = errno;
>         pid_t pid;
>         int status;
> 
>         while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
>             (pid < 0 && errno == EINTR))
>                 ;
> 
>         signal(SIGCHLD, main_sigchld_handler);
>         errno = save_errno;
> }
「うーん、やっぱりハンドラー関数の中で自分を再度セットしてるよな。
 しかも、 signal() で。
 その上には waitpid() のループしかないしなー・・・・・
 waitpid() のループ!!!」

某所のソースを確認。
う、やっぱり。
[FDclone-users:00150] で私の書きました
> void ExitChild(int iSignal)
> {
>     pid_t iPid = 0;
> 
>     (省略)
> 
>     /* シグナルの再セット */
>     SetSignalFunc();
> 
>     return;
> }
の省略部分は大雑把に書くと、

--- ここから ---
    do {
        /* 終了した子プロセスを取得 */
        iPid = waitpid((pid_t)0, &iStatus, WNOHANG);
        if (iPid < 1) {
            break;
        }

        /* 自分の子供のリストから iPid の検索 */

        /* みつかった pid の終了時間を今の時刻に */
    } while (1);
--- ここまで ---

と、同様に waitpid() のループでした。
ではと、[FDclone-users:00150] で書きました、かの暴走プログラムの
main() にいる wait() をコメントにし、CatchSIGCHLD() の頭に
waitpid() のループを入れたら見事に暴走がとまりました。
(あのソースぐらいだとループにしなくても大丈夫でしたが)
signal() でも sigaction() でも同じように動くようです。

waitpid() の man をみても特に記述は見られないのでただの観測結果
なのですが、自分の備忘録をかねてお知らせいたします。

http://www16.boulder.ibm.com/doc_link/en_US/a_doc_lib/libs/basetrf2/wait_waitpid_wait3_wait364.htm

# ちなみに、上記の URL (自体)をみて初めて waitpid() の man の
# 呼び出し方がわかりました
# $ man 1 wait 
# は、日本語でその manual が表示されるのですが、
# $ man 2 wait
# wait に対するエントリがセクション 2 にありません。
# とでるので、 wait() の manual が存在していないとばかり
# 思っていましたが、
# $ man 2 wait_waitpid_wait3_wait364
# でやっと英語の manual が出てきました。
# AIX install program が symlink を作ってくれなかっただけらしい。