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

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



潮田@今日もお遊びで出社中です。
ちょっと長いです。


Takashi SHIRAI <shirai@unixusers.net> wrote:

>  trap_common() は shell の基本機能として重要な部分ではない
> ので、中身をそっくり削除してしまっても大勢に影響はありません。
> なので、system() 以外の行を削除してみて症状が再現するかどう
> か試してみて下さい。
この流れでいくと system() は signal() の typo ですよね。
trap_common() の
	flags = signallist[i].flags;
から
	if (trapped < 0) Xexit2(sig + 128);
までを削除して試しました。
削除前同様の暴走でした。


>  portability を考えるとこの signal() は外せないのですが、も
> し本当に signal() が SIGCHLD を発生させているのだとしたら、
> sigaction() に置換えてみましょうか。
>  それで直るとしたら、OS 側で用意されている library 実装が原
> 因ということになるでしょうか。
> 
> 	if (signallist[i].func) {
> 		struct sigaction act;
> 
> 		act.sa_handler = (sigcst_t)(signallist[i].func);
> 		act.sa_flags = 0;
> 		sigemptyset(&act.sa_mask);
> 		sigaction(sig, &act, NULL);
> 	}
これは、暴走しませんでした。
今日たまたまきている者に AIX 4.3.3 をかりて試しましたが、
そちらでも暴走することなく終了しました。
ただ、このためしたマシンが
oslevel -r 
になにも答えないおかしな環境だったので、休み明けにもう少し
素性の知れた WS でも試します。

>  FDclone の中で SIGCHLD を特別扱いしている箇所は 3 箇所だけ
> だと思います。
> 	1. trap_chld() の中で checkjob() を呼んでいる。
> 	2. makechild() の中で SIGCHLD の mask を外している。
> 	3. posixsh.c/gettermio() の中で SIGCHLD の block 対
> 	   象に追加している。
>  それぞれ該当箇所は 1 行のみですので、その 1 行を削除してみ
> ることで、元のままの trap_common() でも支障なく動作したりす
> るようであれば、別のところに原因があるということになりますね。
>  一度試してみて下さい。
3通りすべて試しましたが、同様に暴走しました。



以下は余談気味。
で、そういえばと思い出したものがあります。
去年入社の新人が秋頃に AIX でだけ暴走しますと言ってきた
プログラムがありました。
そんなに長くないのでそのまま貼り付けますと、

--- ここから ---
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

static void CatchSIGCHLD(int iSignal);
static void SetSignal(void);

static int iCount = 0;

int main(int argc, char *argv[])
{
        int i = 0;
        int j = 0;
        pid_t iPid = 0;

        do {
                SetSignal();
                for (i = 0; i < 10; i++) {
                        iPid = fork();
                        if (iPid == 0) {
                                _exit(0);
                        }
                        else {
                                wait(&j);
                        }
                }

        } while (0);

        return 0;
}

/* SIGCHLDを受けたらプリント */
static void CatchSIGCHLD(int iSignal)
{
        iCount++;

        printf("Hello[%d]!! pid(pid=%d)\n", iCount, getpid()); fflush(stdout);

        SetSignal();

        return;
}

/* ハンドラーのセット */
static void SetSignal(void)
{
        signal(SIGCHLD, CatchSIGCHLD);

        return;
}
--- ここまで ---

これは、
shiota@alpha <~> $ ./a.out
Hello[1]!! pid(pid=58052)
Hello[2]!! pid(pid=58052)
Hello[3]!! pid(pid=58052)
Hello[4]!! pid(pid=58052)
Hello[5]!! pid(pid=58052)
Hello[6]!! pid(pid=58052)
Hello[7]!! pid(pid=58052)
Hello[8]!! pid(pid=58052)
Hello[9]!! pid(pid=58052)
Hello[10]!! pid(pid=58052)
shiota@alpha <~> $
こんな風な結果を期待しており、実際 FreeBSD(x86) や Linux(alpha)
ではそうなりました。
が、 Tru64 上では、
-bash-2.05b$ ./a.out
Hello[1]!! pid(pid=234322)
Hello[2]!! pid(pid=234322)
Hello[3]!! pid(pid=234322)
Hello[4]!! pid(pid=234322)
Hello[5]!! pid(pid=234322)
Hello[6]!! pid(pid=234322)
Hello[7]!! pid(pid=234322)
Hello[8]!! pid(pid=234322)
Hello[9]!! pid(pid=234322)
-bash-2.05b$
と 10 番目が出力されません。
そして本命の AIX ですが
shiota@delta <~/ss> $ ./a.out
(すごく省略)
Hello[206416]!! pid(pid=33884)
Hello[206417]!! pid(pid=33884)
Hello[206418]!! pid(pid=33884)
Hello[206419]!! pid(pid=33884)
Hello[206420]!! pid(pid=33884)
Hello[206421]!! pid(pid=33884)
Hello[206422]!! pid(pid=33884)
Hello[206423]!! pid(pid=33884)
Illegal instruction
shiota@delta <~/ss> $
(Illegal の前に化け文字が出てましたが消しています)
と暴走・リソースを食いつぶし、その内おちるしまつ。
結局この解決方法は見つからず、この新人が退社(はやっ)したため
問題ごと頭から消していました。

前回述べました某所のソースには、

--- ここから ---
/********************************/
/*** シグナルをセットする関数 ***/
/********************************/
void SetSignalFunc(void)
{
    signal(SIGTERM, KillChild);
    signal(SIGCHLD, ExitChild);
    signal(SIGINT, SIG_IGN);
    signal(SIGQUIT, SIG_IGN);
    signal(SIGHUP, SIG_IGN);
    signal(SIGTSTP, SIG_IGN);

    return;
}
/**************************************/
/*** 子プロセスの終了処理をする関数 ***/
/**************************************/
void ExitChild(int iSignal)
{
    pid_t iPid = 0;

    (省略)

    /* シグナルの再セット */
    SetSignalFunc();

    return;
}
--- ここまで ---


と書いた部分があるだけに、この動作は理解できないのですが、
力不足で見ないふりです。
(この ExitChild() は、日中に毎日一万回以上よばれているんですけれ
ど、なぜ動いているのだろう)