パイプが壊れてもプログラムは終了しませんか?
-
01-07-2019 - |
質問
2 つのプロセスをパイプし、パイプの「出力」で 1 つを強制終了すると、最初のプロセスは「Broken Pipe」シグナルを受信し、通常はそれも終了させていました。例えば。ランニング
$> do_something_intensive | less
そして終了します 少ない SuSE8 以前のリリースでは、応答性の高いシェルにすぐに戻るために使用されていました。今日それを試してみたら、 集中的に何かをする 手動で強制終了するまでは明らかにまだ実行されています。何かが変わったようです(glib?シェル ?) プログラムが「壊れたパイプ」を無視するようにします...
これについてヒントを持っている人はいますか?以前の動作を復元するにはどうすればよいですか?なぜ変更されたのか (または、なぜ常に複数のセマンティクスが存在していたのか)?
編集 :さらなるテスト (strace を使用) により、「SIGPIPE」が明らかになります。 は 生成されますが、プログラムは中断されません。シンプルな
#include <stdio.h>
int main()
{
while(1) printf("dumb test\n");
exit(0);
}
無限に続くだろう
--- SIGPIPE (Broken pipe) @ 0 (0) ---
write(1, "dumb test\ndumb test\ndumb test\ndu"..., 1024) = -1 EPIPE (Broken pipe)
いつ 少ない 殺される。プログラム内でシグナルハンドラーをプログラムして確実に終了させることはできますが、プログラムを SIGPIPE で強制的に終了させる環境変数またはシェルオプションを探しています。
再度編集します:これは tcsh 固有の問題 (bash が適切に処理する) であり、端末に依存する (Eterm 0.9.4) ようです。
解決 3
アドバイスのおかげで解決は近づいています...
tcsh のマンページによると、「非ログイン シェルは親から終了動作を継承します。他の信号には、シェルが親から継承した値が含まれています。」
それは私を示唆しています ターミナル 実はそれが問題の根源なのです...SIGPIPE を無視した場合、シェル自体も SIGPIPE を無視します...
編集: この問題は Eterm + tcsh でのみ発生するという決定的な確認があり、Eterm ソース コードに疑わしい欠落シグナル (SIGPIPE、SIG_DFL) が見つかりました。これで事件は解決すると思います。
他のヒント
リーダーが去った後にパイプに書き込もうとすると、SIGPIPE シグナルが生成されます。アプリケーションにはこのシグナルをキャッチする機能がありますが、キャッチできない場合はプロセスが強制終了されます。
SIGPIPE は、呼び出しプロセスが書き込みを試行するまで生成されないため、出力がなくなると生成されません。
「何か集中的なことをする」ということは少し変わりましたか?
ダニエルが述べたように、SIGPIPE は「パイプが消えた」という魔法の信号ではなく、「頑張ってください。そのパイプの読み取り/書き込みはもうできません」という信号です。
「集中的に何かを行う」を制御できる場合は、回転中に「進行状況インジケーター」出力を書き出すように変更できます。これにより、適切なタイミングで SIGPIPE が起動されます。