孤児プロセスグループでは、対話型シェルは何をすべきですか?

孤児プロセスグループでは、対話型シェルは何をすべきですか?

(次の提案に基づいてUnixに再投稿しました。https://stackoverflow.com/questions/13718394/what-should-interactive-shells-do-in-orphaned-process-groups)

簡単な質問は、シェルがttyを所有していない孤立したプロセスグループにある場合はどうすればよいかということです。しかし、この長い質問は興味深いので読んでください。

あなたのお気に入りのケースを使ってラップトップをポータブルヒーターに変えるための面白くて面白い方法は次のとおりです(あなたは奇妙な人ではありません)。

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

これにより、bashはCPUを100%に固定します。 zsh と Fish は同じことを行いますが、ksh と tcsh はジョブ制御に対して呟きを放棄します。これは少し良くなりますが、それほど良くはありません。ああ、そしてこれはプラットフォームに依存しない攻撃者です。 OS XとLinuxの両方が影響を受けます。

私の(おそらく間違った)説明は次のとおりです。サブシェルが前景にないことを検出しましたtcgetpgrp(0) != getpgrp()。だから自分で停止しようとしますkillpg(getpgrp(), SIGTTIN)。しかし、プロセスグループは、親プロセス(Cプログラム)がリーダーであり、死んだので孤児となり、孤児にSIGTTIN送られたプロセスグループは捨てられました(そうでなければ何も再開できません)。したがって、サブシェルは停止せず、まだバックグラウンドにあるため、すべての操作をすぐにやり直します。すすぎ、繰り返します。

私の質問は、コマンドラインシェルがこの状況をどのように検出してどうすればよいですか? 2つの解決策がありますが、理想的ではありません。

  1. pidがグループIDと一致するプロセスにシグナルを送信します。失敗すればESRCH孤児になることもできるという意味だ。
  2. ブロックされていない方法でバイトを読み取ろうとします/dev/tty。失敗すればEIO孤児になることもできるという意味だ。

(これを追跡する問題は次のとおりです。https://github.com/fish-shell/fish-shell/issues/422)

あなたの考えに感謝します!

答え1

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

tcsetattrまた、プロセスグループが孤児になった場合は戻りを意味しますEIO(そしてSIGTTをブロック/無視しません)。ヨーロッパreadこれは、端末の方法より侵襲性が低い方法かもしれません。

次のコマンドを使用して再現できます。

(bash<&1 &)

それ以外の場合、バックグラウンドでコマンドを実行すると、stdinは/ dev / nullにリダイレクトされます。

(bash<&1 & sleep 2)

ターミナルから2つのシェルを読み取るので、より奇妙な動作を提供します。これは無視されSIGTTIN、新しいプロセスが検出されず、一度起動した後はフォアグラウンドプロセスグループに属しなくなりました。

ksh93解決策は悪くありません。放棄する前に(無限ではなく)最大20回だけループを実行してください。

関連情報