久しぶりに小ネタです。
Windowsでの Socket(WSOCK系)はバークレーソケットな仕様なので、あまり手を加えずにLinuxやらその他に移植ができますが、ちょっとした落とし穴にハマったので、備忘録ついでに。
WindowsのあるコードからLinuxに移植したプロセスを動かしていると、切断テストをしたときに、時々なんか落ちるという事態に遭遇。。。
Windowsで同じようなプログラムを組んでもちゃんとsend()からエラーが帰ってきてしかるべき処理ができているのになぁ…といった具合でした。
で、よくよく調べてみると、send関数はこちらがsendの最中に相手側からの不意な切断があった場合にSIGPIPEが発生するということが判明。
man send をよくみたらこんなことがかいてありました。。
フラグ引き数
flags 引き数は、以下のフラグの (0 個以上の) ビット単位の論理和を とったものを指定する。
(略)
MSG_NOSIGNAL (Linux 2.2 以降)
ストリーム指向のソケットで相手側が接続を切断した時に、エラーとして SIGPIPE を送信しないように要求する。この場合でも EPIPE は返される。
あー、やっぱりmanはちゃんと見なきゃいけないなぁと思った次第。
対処法としては、sendのflags引数にMSG_NOSIGNAL
を追加するか、signal(SIGPIPE,ハンドラ)
とかやって、ハンドラ関数で適切に処理することぐらいですね。。
MSG_NOSIGNAL
を設定しても途中で送信切断が帰ってきたらエラー普通に戻ってきますので、良さそうな感じではあります。
ちなみに、Windows Socket(WSOCK系)には当然こんなものはないので、移植には注意ということでした。