壊れたパイプでUnixプロセスが死ぬ原因は何ですか?


30

ここに私が考えたいくつかのオプションがありますが、どちらが正しいかはわかりません。

  1. パイプからの読み取り中にI / Oエラーが発生しました。
  2. パイプのもう一方の端に書き込むプロセスが失敗して終了しました。
  3. パイプに書き込むことができるすべてのプロセスがパイプを閉じました。
  4. パイプの書き込みバッファがいっぱいです。
  5. ピアは、二重パイプのもう一方の方向を閉じました。
  6. パイプから読み取ることができるプロセスがないため、書き込みに失敗しました。
  7. システムコールがEPIPEエラーを返しましたが、エラーハンドラがインストールされていませんでした。

あなたの質問は何ですか?それらのどれが正しいのか、またはパイプの破損を引き起こす可能性のある他の何かがあるかどうかを尋ねていますか?
EightBitTony

@EightBitTonyこれらのうち正しいもの
siamii

回答:


38

プロセスは、リーダーが残っていないタイプSOCK_STREAMのパイプ(名前付きまたは名前なし)またはソケットに書き込もうとすると、SIGPIPEを受け取ります。

一般的には振る舞いが望まれます。典型的な例は次のとおりです。

find . | head -n 1

find一度head終了すると実行を続けたくない(そして、そのパイプで読み取りのために開いている唯一のファイル記述子を閉じた)。

yesコマンドは、一般的に終了させるために、その信号に依存しています。

yes | some-command

何らかのコマンドが終了するまで「y」を書き込みます。

コマンドが終了するときだけでなく、すべてのリーダーがパイプへの読み取りfdを閉じたときでもあることに注意してください。に:

yes | ( sleep 1; exec <&-; ps -fC yes)
      1 2       1        0

サブシェルがそのstdinを明示的に閉じた後、パイプから1(サブシェル)、2(サブシェル+スリープ)、1(サブシェル)、そして0 fdの読み取りがありyes、SIGPIPEを受け取ります。

上記では、ほとんどのシェルはpipe(2)whileをksh93使用socketpair(2)しますが、その点で動作は同じです。

プロセスは、(一般的に、書き込みシステムコールをSIGPIPEを無視するとwrite、することができるがpwritesendsplice...)とのリターンEPIPEエラー。そのため、破損したパイプを手動で処理したいプロセスは、通常SIGPIPEを無視し、EPIPEエラーが発生したときにアクションを実行します。


14

(6)

パイプから読み取ることができるプロセスがないため、書き込みに失敗しました。

記述子とフォークを複製しない限り、開始できるプロセスは1つだけです。通常、パイプには1つのリーダーと1つのライターがあり、そのうちの1つが接続を閉じると、パイプは無効になります。名前付きパイプを使用している場合、複数の接続を(シリアルで)行うことができますが、この意味ではそれぞれが新しいパイプを表します。したがって、スレッドまたはプロセスへの「パイプ」はファイル記述子と同義です。

からman 7 pipe

パイプの読み取り終了を参照するすべてのファイル記述子が閉じられている場合、write(2)は呼び出しプロセスに対してSIGPIPEシグナルを生成します。呼び出しプロセスがこのシグナルを無視している場合、write(2)はエラーEPIPEで失敗します。

したがって、「壊れたパイプ」は、ライターにとってEOFがリーダーにとって何であるかです。


0

書き込みプロセスの前に読み取りプロセスが終了すると、パイプの破損が発生します。だから私は(6)


2
パイプに対して読み取りまたは書き込みを行うプロセスがいくつかあり、同じプロセスが読み取りと書き込みを行うことができます。また、終了することではなく、ファイル記述子を閉じることです。
ステファンシャゼラス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.