SIGPIPE を防ぐ方法 (または適切に処理する方法)

通常、SIGPIPE は無視します。 コードでエラーを直接処理します。これは、C のシグナル ハンドラーには、できることに多くの制限があるためです。

これを行う最も移植性の高い方法は、 SIGPIPE を設定することです SIG_IGN へのハンドラ .これにより、ソケットまたはパイプの書き込みが SIGPIPE を引き起こすのを防ぐことができます

SIGPIPE を無視するには 次のコードを使用してください:

signal(SIGPIPE, SIG_IGN);

send() を使用している場合 呼び出し、別のオプションは MSG_NOSIGNAL を使用することです SIGPIPE を有効にするオプション 呼び出しごとに動作をオフにします。すべてのオペレーティング システムが MSG_NOSIGNAL をサポートしているわけではないことに注意してください。

最後に、SO_SIGNOPIPE も考慮する必要があります。 setsockopt() で設定できるソケットフラグ 一部のオペレーティング システムでは。これにより、SIGPIPE が防止されます 設定されているソケットへの書き込みだけが原因ではありません。


もう 1 つの方法は、write() で SIGPIPE を生成しないようにソケットを変更することです。これは、SIGPIPE のグローバル シグナル ハンドラーが不要なライブラリでより便利です。

ほとんどの BSD ベース (MacOS、FreeBSD...) システム (C/C++ を使用していると仮定) では、次の方法でこれを行うことができます:

int set = 1;
setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));

これにより、SIGPIPE シグナルが生成される代わりに EPIPE が返されます。


私はパーティーに遅刻しましたが、SO_NOSIGPIPE 移植性がなく、システムで動作しない可能性があります (BSD のようです)。

たとえば、SO_NOSIGPIPE のない Linux システムを使用している場合の優れた代替手段 MSG_NOSIGNAL を設定することです send(2) 呼び出しのフラグ。

write(...) を置き換える例 send(...,MSG_NOSIGNAL) (nobar のコメントを参照)

char buf[888];
//write( sockfd, buf, sizeof(buf) );
send(    sockfd, buf, sizeof(buf), MSG_NOSIGNAL );