通常、キャッチする代わりにSIGPIPE
それを無視します。これにより、プログラムが黙って終了する代わりにwrite
失敗します。EPIPE
ただし、パイプへの書き込み時にエラーが発生するSIGPIPE
場合は、再試行しないでください。それは決してうまくいきません。 SIGPIPE
は、パイプにリーダーがないことを意味します。現在、パイプにリーダーがない場合、リーダーはありません。(このように考えてみてください: リーダーのないパイプはどのようにしてリーダーを取得するのでしょうか? それは不可能です!)
あなたの問題は、パイプのもう一方の端を閉じていることです。それを修正し、心配しないでくださいSIGPIPE
。 SIGPIPE
症状だけです。
編集:ここで答える質問が 2 つあります。これらの質問の両方に答えられない場合は、処理を気にしないでくださいSIGPIPE
。
私のプログラムが受け取る原因は何SIGPIPE
ですか? 受信する唯一の方法SIGPIPE
は、パイプの読み取り側を閉じることです。これは、読み取りプロセスがクラッシュした場合、またはパイプを閉じるようにプログラムされている場合に発生します。ネットワーク サーバーを作成している場合、または未知のプロセスと通信している場合、これはよくあることです。ただし、両方のプログラムを作成し、両方ともローカルで実行する場合は、プログラミング エラーを示している可能性があります。
をキャッチしたとき、私のプログラムは何をしSIGPIPE
ますか? パイプを使用してサーバーと通信するクライアント プロセスを作成している場合、何をすべきSIGPIPE
でしょうか? 再試行することはできません。通常、クライアントは接続先のサーバーを再起動できません。賢明なデフォルトのことをしてSIGPIPE
、プログラムを終了させてください。ただし、サーバーがクライアントにデータを送信している場合、サーバーが制御して取得すると、クライアントが再起動SIGPIPE
する可能性があります。しかし、これは非常に悪い考えかもしれません。たとえば、クライアントが決定論的である場合、クライアントは再びクラッシュするだけであり、単純なクラッシュではなく無限ループに陥ります。
したがって、ここでの一般的な格言は、「処理する準備ができているエラーのみをキャッチする」です。完全を期すためだけにエラーをキャッチしないでください。プログラムをクラッシュさせたり、操作を失敗させたりするだけで、後で戻ってデバッグできます。
コード スニペット:これは、私のプロジェクトの 1 つからのコード スニペットです。実行しても、SIGPIPE
プロセスは終了しません。代わりにwrite
、エラーが生成されEPIPE
ます。ネットワークサーバーを作成している場合EPIPE
、クライアントが突然切断される可能性のある方法の 1 つです。
void
ignore_sigpipe(void)
{
struct sigaction act;
int r;
memset(&act, 0, sizeof(act));
act.sa_handler = SIG_IGN;
act.sa_flags = SA_RESTART;
r = sigaction(SIGPIPE, &act, NULL);
if (r)
err(1, "sigaction");
}