4

私はシェルを書こうとしています。フォアグラウンド プロセスが実行されると、フォークされたプロセス パイプラインに独自のプロセス グループ ID が与えられます。次に、端末はこのプロセス グループ ID に引き渡され (tcsetpgrp を使用)、シェルはプロセス グループ ID が終了するのを待ってから、再び端末制御を渡します。これは完全に正常に機能します。

発生する問題は、バックグラウンド プロセスを実行しようとしたときに発生します。ここでも、パイプライン内のすべてのプロセスに 1 つのプロセス グループ ID を与えますが、今回はこのグループに端末制御を与えません。実行すると、特定のバックグラウンド コマンドの出力が (実行が終了する前に) 端末に出力され、端末は同時にユーザーにプロンプ​​トを返します。端末に書き込もうとする子プロセスが SIGTTOU を取得して停止するはずですが、これは明らかに起こりません。フォークされたプロセスがすべて同じプロセス グループ ID を持ち、この ID がシェルのものとは異なることを確認しました。

(ctrl-c を使用して) シェルを終了し、それを実行した標準の bash シェルに戻ると、シェルの終了時にバックグラウンド プロセスを取得しなかったため、バックグラウンド プロセスは引き続き実行されます (これは例外です)。奇妙なのは、このプロセスがフォアグラウンド プロセスではないにもかかわらず、bash シェルに出力を書き続けていることです。これにより、このバックグラウンド プロセスが POSIX のバグが原因で SIGTTOU を取得していない (可能性は低い)、SIGTTOU を処理している (停止のデフォルト アクションが無視される)、またはバックグラウンド プロセスが SIGTTOU を無視していると結論付けることができます。

フォークされたプロセスを実行する前に、SIGTTOU を受信したときに停止することを確認する方法はありますか (exec バイナリが何も変更しないと仮定して)。

4

2 に答える 2

1

解決策は、フォークされたプロセスが exec を呼び出す前に以下を実行するようにすることでした。

struct termios term; 
if (tcgetattr(STDIN_FILENO, &term) < 0)
        printf("ERROR\n");
    term.c_lflag = TOSTOP;
    if (tcsetattr(STDIN_FILENO,TCSANOW,&term)<0)
        printf("ERROR\n");
于 2013-10-12T05:50:23.357 に答える