壊れたパイプエラーの原因は何ですか?


83

ピア側のソケットを閉じると、パイプの破損エラーがスローされることを知っています。

しかし、私のテストでは、ピア側が閉じているときにこちら側ですぐに「送信」呼び出しを行うと、必ずしもパイプの破損エラーが発生するとは限らないことに気付きました。

例えば:

ピア側のソケットを閉じた後(closeを呼び出してクリーンクローズを試み、ピアを強制終了して異常なクローズを試みました)、40バイトを送信しようとすると、パイプが壊れることはありませんが、 40000バイトを送信すると、すぐに壊れたパイプエラーが発生します。

パイプの破損の正確な原因とその動作を予測できますか?

回答:


59

ネットワークのクローズが監視されるまでに時間がかかる場合があります。合計時間は、クローズ後、ポート宛てのパケットがすべてデッドであると見なされるまで、通常は約2分(はい、分!)です。エラー状態はある時点で検出されます。小さな書き込みでは、システムのMTU内にいるため、メッセージは送信のためにキューに入れられます。書き込みが大きいと、MTUよりも大きくなり、システムは問題をより迅速に発見します。SIGPIPEシグナルを無視すると、関数は壊れたパイプでEPIPEエラーを返します-接続の切断が検出されたある時点で。


4
@varevarao:送信をキューに入れて特定の間隔で送信することは回避策ではないと思います。アプリケーションが遅延に耐えられる場合は、送信するMTUが増えるまで送信をキューに入れることが回避策になる可能性があります。
ジョナサンレフラー2012

11

ソケットの現在の状態は、「キープアライブ」アクティビティによって決定されます。あなたの場合、これはあなたがsend呼び出しを発行しているときに、keep-aliveアクティビティがソケットがアクティブであることを伝え、そのためsend呼び出しが必要なデータ(40バイト)をバッファに書き込み、エラーを出さずに戻る可能性があります。

より大きなチャンクを送信する場合、send呼び出しはブロッキング状態になります。

送信者ページでもこれを確認しています。

メッセージがソケットの送信バッファに収まらない場合、ソケットが非ブロックI / Oモードになっていない限り、send()は通常ブロックします。非ブロッキングモードでは、この場合はEAGAINが返されます

したがって、使用可能な空きバッファをブロックしているときに、(キープアライブメカニズムによって)呼び出し元にもう一方の端が存在しないことが通知された場合、送信呼び出しは失敗します。

上記の情報では正確なシナリオを予測することは困難ですが、これが問題の原因であると私は信じています。


1
ソケットの現在の状態は、ACKアクティビティによって監視されます。キープアライブは、マイナーなソースACKアクティビティの1つにすぎず、デフォルトではオフになっています。
ローン侯爵2016年

3

たぶん、40バイトはパイプバッファに収まりますが、40000バイトは収まりませんか?

編集:

閉じたパイプに書き込もうとすると、送信プロセスにSIGPIPEシグナルが送信されます。信号がいつ送信されるか、またはパイプバッファがこれにどのような影響を与えるかは正確にはわかりません。sigaction呼び出しでシグナルをトラップすることにより、回復できる場合があります。


0

ピアを閉じると、送信を停止するだけなのか、送信と受信の両方を停止するのかがわかりません。TCPではこれが許可されているため、閉じるとシャットダウンの違いを知っておく必要があります。ピアが送信と受信の両方を停止した場合、最初にいくつかのバイトを送信すると、成功します。ただし、ピアカーネルはRSTを送信します。したがって、その後いくつかのバイトを送信すると、カーネルはSIGPIPEシグナルを送信します。このシグナルをキャッチまたは無視した場合、送信が戻ったときにパイプの破損エラーが発生するか、そうでない場合、プログラムのデフォルトの動作がクラッシュします。 。


-1

新しいネットワークが設置された後、パイプの破損エラーが発生しました。ポート9100が開いていて、telnetポート9100を介してプリンターに接続できることを確認した後、プリンタードライバーを「HP」から「GenericPDF」に変更しました。パイプの破損エラーがなくなり、正常に印刷できました。

(RHEL 7、プリンターはRicohブランドであり、HP構成は既存であり、以前のネットワークで機能していました)

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