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

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



 しらいです。

In Message-Id <03May6.172153jst.119051@inetgw.lightwell.co.jp>
        SHIOTA Shoichi <Shoichi.Shiota@lightwell.co.jp>さんwrites:
> 潮田です。

> > > POSIX.1 には、SIGCHLD に対するシグナルハンドラを設定したときに、
> > > wait すべき終了した子が存在する場合にシグナルが生成されるかどう
> > > かの記載がない。これは、上述の動作を許す。しかし、POSIX.1 では、
> > > シグナルが発生してもそのシグナルに対する動作をデフォルトに戻さな
> > > い (POSIX.1 の sigaction 関数を使って動作を設定したと仮定する)
> > > ので、ハンドラ内で SIGCHLD のシグナルハンドラを設定する必要はな
> > > い。
> これは、
> 「POSIX.1 では、ハンドラ内で SIGCHLD のシグナルハンドラを設定する
>  必要はない。
>  しかし、 POSIX.1  では、動作が・・・(上述)のような実装を許容して
>  おり、この場合はハンドラ内で SIGCHLD のシグナルハンドラを設定
>  してはいけない。」
> ぐらいに解するのでしょうか。

 この本は UNIX の bible なので私も新旧両方持っているのです
が、会社に置いてあるために最近忙しくて読めていませんでした。
今朝読んで私もこれが原因かと思いました。
 ここで書かれているのは「POSIX では」とあるとおり signal()
ではなく sigaction() を使った場合の話で、signal() を使った場
合は SA_RESETHAND がどうなっているかが未定義なので、再設定は
不要とも設定禁止とも言えないと思います。
 なので、POSIX 的には「signal() は使用禁止」と読むべきかも
知れませんね。


> > if (sig != SIGCHLD)
> >      signal(sig, (sigcst_t)(signallist[i].func));
> これでも、2度目以降の子供の終了時に trap_chld() へ飛んで
> きますから、再度のセットが必要ないのは確かでしょうが、
> なんだかなーって感じですね。

 古い signal() の実装では SIG_DFL に設定されてしまいますか
ら、新しい実装では不要であってもこの部分の code は削る訳には
いかないでしょう。

 google ってみると、handler 再設定の話は ruby でも俎上に上
ったことがあるようで、再設定の要不要を configure で判別する
ことの困難さが話題になっていたようです。
 FDclone の policy では、例えある環境では不要の code であっ
ても、別の環境では必須の code であるようなら、無駄を承知の上
で実装しておく方が安全だという判断に基づいています。
 performance よりも portability を重視した結果の判断なので
すが、他に何か良い解があるようならどなたかご示唆下さい。


> SIGCHLD だけ、特別扱いでも良いのでしょうが、やはり sigaction() 
> への書き換えですかね。

 POSIX には SIGCHLD の再発呼に関する記述が全く無い訳で、こ
れを厳格に評価するならば、sigaction() を使った場合に再発呼さ
れないことは保証されていないことになります。
 また、AIX の signal(3) の挙動は SVR3 互換の signal(2) の仕
様を敢えて模した結果であり、多分 SVR3 以前の SystemV では、
sigaction(2) が使えないために signal(2) を使うことで同じ結果
を生んでしまう筈です。
 ということで、万全を期した解は「handler 内で wait する」し
かないのかも知れません。

---- Cut Here ----
diff -u ../old/FD-2.03a/system.c ./system.c
--- ../old/FD-2.03a/system.c    Tue Apr 15 00:00:00 2003
+++ ./system.c  Tue May  6 00:00:00 2003
@@ -2219,8 +2219,12 @@
 #ifdef SIGCHLD
 static int trap_chld(VOID_A)
 {
-# if	!MSDOS && !defined (NOJOB)
-	if (bgnotify) checkjob(1);
+# if	!MSDOS
+#  ifdef	NOJOB
+	while (waitjob(-1, NULL, WNOHANG | WUNTRACED) > 0);
+#  else
+	checkjob(bgnotify);
+#  endif
 # endif
	return(trap_common(SIGCHLD));
 }
---- Cut Here ----

 2.03a に対する patch を考えてみました。素の 2.03a と、この
patch 適用後の比較をしたいので、AIX 環境で以下の検証をしてみ
て頂けないでしょうか?
	0. system.c l.1529 の「#ifdef NOJOB」を「#if 0」に書
	   換えて「make sh bsh all」を実行。
	1. ./fd で PAGER や EDITOR 等の子 process を起動する。
	2. ./fdsh で sleep や /bin/echo 等の子 process を起
	   動する。
	3. ./fdsh で「&」付の back ground job として 2. と同
	   様の検証。
	4. ./fd で set -b を実行した後 1. と同様の検証。
	5. ./fdsh で set -b を実行した後 2., 3. と同様の検証。
	6. ./fdbsh で 2., 3. と同様の検証。
	7. patch 適用後、system.c l.1529 の「#ifdef NOJOB」
	   を「#if 0」に書換えて「make sh bsh all」を実行。
	8. 作りなおした ./fd, ./fdsh, ./fdbsh に対して 1.-6.
	   を再度検証。

 -DNOJOB 時に SIGSEGV にならないのは、0. や 7. にある箇所が
原因で、NOJOB 時にはそもそも SIGCHLD を捕捉していないからだ
と思います。
 これを書換えることで、-DNOJOB 時にも同じ症状が再現するか否
かの検証が 1.-6. になります。./fdbsh は -DNOJOB で作られます
から、./fdbsh でも再現するようになるなら問題の本質を捉え易く
なります。
 これが 7. の patch 適用により全てのケースで解消されるよう
であれば、この実装で暫く様子を見てみて下さい。


> SIG_DFL に戻らないシグナルは SIGCHLD だけではないですし。
> 現在直接の原因は signal(SIGCHLD, ) が SA_RESETHAND をセットして
> しまうことだと [FDclone-user:00155] で分かっていますが、
> これは、 SA_RESETHAND (のみ)をセットすること自体が問題なのか、
> この値のときに、ああいった動作をすることが問題なのかも、私には
> 判断がつけられません。

 そもそも SA_RESETHAND には「wait されていない SIGCHLD は再
発呼する」という意味はない筈ですが、SVR3 の signal() との互
換性を実現するために、AIX では SA_RESETHAND にこの意味を追加
させてしまったんだと思います。

 そういう意味では HP-UX についても全く同じことが言える筈で
すが、HP-UX の signal() は SA_RESETHAND だけでなく SA_NOCLDSTOP
も有効にしているので、この合わせ技により signal() を使っても
無限 SIGCHLD 発呼が回避出来ているのかも知れません。
 [FDclone-users:00155] の実験で、sa_flags = SA_RESETHAND |
SA_NOCLDSTOP にしてみると無限発呼が解消されたりはしませんか?
AIX ではこの併用の効果は無かったようですけど。

# 後は SVR3 上で 0-8. の検証が出来れば良いのですが、どこか
#に古い機械が転がってませんかね?
# HP-UX だと 7.0 辺りから段階的に SVR3 -> SVR4 に移行して
#いるようで、signal() の旧実装が 7.0-10.0 のどこで消えたの
#か判りません。
# AIX だと 3.x 以降が SVR4 らしいです。A/UX だと 2.x 以降。
#意外と IRIX 辺りが未だに SVR3 のままの実装を引きずっている
#かも知れません。

                                               しらい たかし