ruby/perl のsyswrite について話したあとばたんと寝てたら、寝てる間に ruby コミッタと linux kernel コミッタがやってきて write(2) の制約であることが明らかになっていた
[socket] / “非ブロッキングI/O - s-kitaの日記” http://t.co/QyzWczlhV8
2013-03-15 00:36:18@kazeburo そういう話、詳解UNIXプログラミングでだいたい覚えた気がしますね。あれはいつも手元にほしい……。
2013-03-15 00:39:40@tagomoris @kazeburo UNIXのwrite(2)なら、blockingでも全部書いてくれる保証はないはずです。ただ少なくとも1バイト書くまではブロックしてくれる。PIPE_BUFサイズまではアトミックに書けるという話もたしか。
2013-03-15 01:09:11@tagomoris @kazeburo 詳解UNIXは分厚すぎて手元にあっても開くのが億劫になるレベルなので、manが良いですね。基本的な事項なら日本語のでも。
2013-03-15 01:10:50@tagomoris @frsyuki @kazeburo あああ、なんかたぶん pipe とそれ以外でも違うかな……。自信なくなってきた
2013-03-15 01:12:23@tagomoris @kazeburo 書き出し先がファイルでLinuxの場合? 例えばソケットやpipeに2GB書こうとしたケースで、そもそもソケットやpipeのバッファは2GBもないので1発では書けないはず。
2013-03-15 01:14:29man 2 write によると、書き込み先が物理メディアで物理的に空きが無い場合(もしくはlimitかかっている場合)、および割り込みがあった場合には count 以下のバイト数になることがある、とある
2013-03-15 01:15:24@frsyuki @kazeburo そのときはバッファのflush(相手への転送)と空いたバッファの充填を繰り返して全データはけるまで繰り返すはず。nonblockの場合は1発でできなければ1発分だけやって戻る。
2013-03-15 01:16:38@tagomoris 少なくとも insufficient space on the underlying physical medium, RLIMIT_FSIZE, was interrupted by a signal handler
2013-03-15 01:29:10@tagomoris @kazeburo "少なくとも1バイト"というわけではないっぽいですね…orz カーネル空間でもループしてくれる。でも容量不足とかのエラーが発生したり、シグナルとかで割り込まれるとそこで中断して、エラーは返さずにそこまでのバイト数を返す。
2013-03-15 01:33:22@tagomoris rubyのsyswriteですが、2GBは書いてくれないですねぇ。https://t.co/QFQR7GkcXL
2013-03-15 01:38:57@frsyuki おやまあ、ほんとだ。なんでだろ…… size_t を signed int32 固定で扱ってるからっぽいな
2013-03-15 01:40:09@tagomoris @kazeburo SSIZE_MAX を超えたら、実装依存で書き込み途中で帰っても良いらしいです。SSIZE_MAX は ((unsigned)-1 >> 1)。 http://t.co/6MJSBrhv36
2013-03-15 01:40:44