子プロセスが親と一緒に死ぬUNIXバリアントはありますか?


41

Linuxカーネルの動作をかなり長い間研究してきましたが、次のことが常に明らかでした。

プロセス・ダイは、そのすべての子がバックに与えられている場合にはinit、プロセス(PID 1)彼らは最終的に死ぬまで。

しかし、最近、カーネルについて私よりもはるかに多くの経験を持っている人が私に言った:

プロセスが終了すると、そのすべての子も死にます(使用NOHUPした場合を除き、子はに戻りますinit)。

今、私はこれを信じていませんが、私はそれを確かめるためにまだ簡単なプログラムを書きました。sleepすべてがプロセスのスケジューリングに依存しているため、テストに時間()に依存するべきではないことを知っていますが、この単純なケースでは、それで十分だと思います。

int main(void){
    printf("Father process spawned (%d).\n", getpid());
    sleep(5);

    if(fork() == 0){
        printf("Child process spawned (%d => %d).\n", getppid(), getpid());
        sleep(15);
        printf("Child process exiting (%d => %d).\n", getppid(), getpid());
        exit(0);
    }

    sleep(5);
    printf(stdout, "Father process exiting (%d).\n", getpid());
    return EXIT_SUCCESS;
}

これはプログラムの出力であり、話すpsたびに関連する結果がありますprintf

$ ./test &
Father process spawned (435).

$ ps -ef | grep test
myuser    435    392   tty1    ./test

Child process spawned (435 => 436).

$ ps -ef | grep test
myuser    435    392   tty1    ./test
myuser    436    435   tty1    ./test

Father process exiting (435).

$ ps -ef | grep test
myuser    436    1     tty1    ./test

Child process exiting (436).

今、あなたが見ることができるように、これは私がそれを期待していたように非常に振る舞います。孤立プロセス(436)はinit、死ぬまで(1)に戻されます。

ただし、この動作がデフォルトで適用されないUNIXベースのシステムはありますか?プロセスの死がすぐにそのすべての子の死を引き起こすシステムはありますか?

回答:


68

プロセスが終了すると、そのすべての子も死にます(NOHUPを使用しない限り、それらはinitに戻ります)。

これは間違っています。間違っている。それを間違っているか、特定の状況を一般的なケースと混同していると言っている人。

プロセスの死が間接的にその子の死を引き起こす可能性がある2つの方法があります。これらは、端末が閉じられたときに何が起こるかに関連しています。端末が消えると(歴史的には、モデムのハングアップのためにシリアルラインが切断されたため、最近では通常、ユーザーが端末エミュレータウィンドウを閉じたため)、その端末で実行中の制御プロセスに SIGHUP信号が送信れます。その端末で。シェルは通常、終了することでこれに反応します。終了する前に、インタラクティブな使用を目的としたシェルは、開始した各ジョブにHUPを送信します。

シェルからジョブを開始するとnohup、HUPシグナルの2番目のソースが中断されます。これは、ジョブがシグナルを無視し、端末が消えたときに死ぬように指示されないためです。シェルからジョブへのHUPシグナルの伝播を中断する他の方法には、シェルのdisown組み込みコマンドがある場合(シェルのジョブリストからジョブが削除される)、ダブルフォーク(シェルが子を起動する子を起動する)が含まれますそれ自体で、すぐに終了します;シェルはその孫の知識を持っていません)。

繰り返しますが、ターミナルで開始されたジョブは、親プロセス(シェル)が死んだためではなく、親プロセスが殺すように言われたときに親プロセスが殺すことを決定したためです。また、ターミナルの初期シェルは、親プロセスが死んだためではなく、ターミナルが消えたために死にます(これは、ターミナルがシェルの親プロセスであるターミナルエミュレータによって提供されているためか、そうでない場合があります)。


1
3つ目の方法、コントロールグループを使用する方法があります。私が知っているのは、systemdがそれを使用してクリーンキルを強制することだけです。
o11c 14年

5
@JanHudecと混同nohupしていると思いますdisowndisownは、実行中のジョブをジョブテーブルから削除する(シェルのような引数を取る%1)シェルに組み込まれています。その主な有用な副作用は、シェルがSIGHUPをサブプロセスに送信しないことです。nohupは、SIGHUPを無視する(および他のいくつかのことを行う)外部コマンドであり、コマンドラインで渡されたコマンドを開始します。
ジル 'SO-悪である停止' 14

@Gilles:いいえ、私はそうではありませんでしたが、nohup実際にstrace を見るとexec、コマンドになる前にシグナルを無視します。
Jan Hudec 14年

ご回答ありがとうございます!私は、モデムのハングアップに関する歴史的背景が特に気に入った。私は、すべてのカーネル今回...誤解されていた心配し始めていた
ジョンWHスミス

3
また、SIGHUPのデフォルトのシグナルハンドラは終了するため、SIGHUPを受信するとプログラムが終了することにも注意してください。しかし、どのプログラムも独自のSIGHUPハンドラーを実装できます。これにより、親シェルがSIGHUPを送信したときに終了しないことがあります。
スリーブマン14年

12

プロセスが終了すると、そのすべての子も死にます(NOHUPを使用しない限り、それらはinitに戻ります)。

プロセスがセッションリーダーである場合、これは正しいです。セッションリーダーが死亡すると、SIGHUPがそのセッションのすべてのメンバーに送信されます。実際には、その子とその子孫を意味します。

プロセスは、を呼び出すことにより、セッションリーダーになりますsetsid。シェルはこれを使用します。


私はこれについてテストを実行しましたが、あなたが説明している動作を再現できませんでした...プロセスを生成し、新しいセッション(fork、親プロセスを殺すsetsid)を与え、この新しいセッションに別の子をフォークしました。ただし、親プロセス(新しいセッションリーダー)が死んだとき、子はSIGHUPを受け取らず、init最終的に終了するまでアタッチされました。
ジョンWHスミス14年

setpgid(2)マンページから:セッションに制御端末があり、その端末のCLOCALフラグが設定されていない場合、端末のハングアップが発生すると、セッションリーダーにSIGHUPが送信されます。セッションリーダーが終了すると、SIGHUPシグナルも制御端末のフォアグラウンドプロセスグループの各プロセスに送信されます。
ninjalj 14年

1
@ninjaljそれから、セッションリーダーが端末の制御プロセスでもある場合にのみ、この答えが有効であると推測しています。ターミナルから独立した標準のセッションリーダーは、その子を殺しません。それが正しいか?
ジョンWHスミス14年

-1

上記のポスターが言っているのは、子供たちは死なず、親は彼らを殺す(または彼らに終結の合図を送る)ということです。そのため、(1)すべての子の記録を保持し、(2)すべての子に信号を送信するように親をプログラムする場合、あなたが求めるものを持つことができます。

これがシェルの動作であり、親プロセスの動作です。子を殺すのに十分な制御ができるように、親でHUPシグナルをキャッチする必要がある場合があります。


多くの原因により、親が死ぬ可能性があります。たとえば、親がSIGKILLされている場合、子の生存を防ぐ方法はありません。
エミルイェジャベクはモニカをサポートします14

-1

死にかけている親にわずかに関連する答えが少し欠けています。読み取りプロセスのないパイプにプロセスが書き込むと、SIGPIPEが取得されます。SIGPIPEの標準アクションは終了です。

これにより、実際にプロセスが停止する可能性があります。実際には、プログラムがする標準的な方法でyes死にます。

私が実行する場合

(yes;echo $? >&2)|head -10

私のシステムでは、答えは

y
y
y
y
y
y
y
y
y
y
141

141は確かに128 + SIGPIPEです。

   SIGPIPE      13       Term    Broken pipe: write to pipe with no
                                 readers

からman 7 signal


2
しかし、パイプから読み取るプロセスは、必ずしもその親ではありません(通常も)。したがって、これは実際に質問が尋ねているものとは非常に異なるケースです。
バーマー14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.