孤立したプロセスグループでインタラクティブシェルは何をすべきですか?


10

/programming/13718394/what-should-interactive-shells-do-in-orphaned-process-groupsの提案に従ってUNIXに再投稿する)

簡単な質問は、ttyを所有していない孤立したプロセスグループ内にある場合、シェルは何をすべきかということです。しかし、面白いので、長い質問を読むことをお勧めします。

以下は、お気に入りのシェルを使用して、ラップトップをポータブルスペースヒーターに変える楽しくてエキサイティングな方法です(tcshの変人の1人でない限り)。

#include <unistd.h>   
int main(void) {
    if (fork() == 0) {
        execl("/bin/bash", "/bin/bash", NULL);
    }
    return 0;
}

これにより、bashはCPUを100%に固定します。zshとfishは同じことをしますが、kshとtcshはジョブ制御について何かをつぶやいてからキールします。これは少し優れていますが、それほど多くはありません。ああ、それはプラットフォームにとらわれない犯罪者です。OSXとLinuxの両方が影響を受けます。

私の(潜在的に間違っている)説明は次のとおりです:子シェルがそれがフォアグラウンドにないことを検出しました:tcgetpgrp(0) != getpgrp()。したがって、それ自体を停止しようとしますkillpg(getpgrp(), SIGTTIN)。しかし、その親(Cプログラム)がリーダーで死亡したため、そのプロセスグループは孤立SIGTTINしています。孤立したプロセスグループに送信されたものは削除されるだけです(それ以外の場合は、再び起動できません)。したがって、子シェルは停止されませんが、まだバックグラウンドにあるので、すぐにすべてが再び実行されます。すすぎ、繰り返します。

私の質問は、コマンドラインシェルがこのシナリオをどのように検出できるか、そしてそれを行うための正しいことは何ですか?私には2つの解決策がありますが、どちらも理想的ではありません。

  1. pidがグループIDと一致するプロセスにシグナルを送ろうとします。それがで失敗する場合ESRCH、それはおそらく孤立していることを意味します。
  2. から1バイトのノンブロッキング読み取りを試みます/dev/tty。それがで失敗する場合EIO、それはおそらく孤立していることを意味します。

(これを追跡する私たちの問題はhttps://github.com/fish-shell/fish-shell/issues/422です

あなたの考えをありがとう!

回答:


4

私はあなたの分析に同意し、プロセスグループが孤立しているかどうかを検出する必要があるように思えます。

tcsetattrまたEIO、プロセスグループが孤立している場合(およびSIGTT OUをブロック/無視していない場合に戻る)も意味します。これはread、ターミナルでの場合よりも侵入しにくい方法です。

あなたがそれを再現できることに注意してください:

(bash<&1 &)

バックグラウンドでコマンドを実行すると、標準入力が/ dev / nullにリダイレクトされます。

(bash<&1 & sleep 2)

ターミナルから2つのシェルが読み取られることになるため、さらに奇妙な動作になります。SIGTTINいったん開始すると、フォアグラウンドプロセスグループに存在しないことが無視され、新しいものは検出されません。

ksh93のソリューションはそれほど悪くはありません。あきらめる前に、ループを(無限ではなく)20回まで実行するだけです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.