ruby/perl のsyswrite について話したあとばたんと寝てたら、寝てる間に ruby コミッタと linux kernel コミッタがやってきて write(2) の制約であることが明らかになっていた

ruby/perl のsyswrite について話したあとばたんと寝てたら、寝てる間に ruby コミッタと linux kernel コミッタがやってきて write(2) の制約であることが明らかになっていた
28
Sadayuki Furuhashi @frsyuki

Linux本家のmanでも分からなければ、The Open Group spec。

2013-03-15 01:42:08
tagomoris @tagomoris

@frsyuki んでもこれってちょいおかしくないですか? size_t では SSIZE_MAX 以上は普通表すことができないですよね

2013-03-15 01:43:36
Sadayuki Furuhashi @frsyuki

write(2) の挙動、注釈多すぎるだろう… http://t.co/6MJSBrhv36

2013-03-15 01:43:50
tagomoris @tagomoris

あれ、size_t ってunsignedだっけ

2013-03-15 01:44:24
Sadayuki Furuhashi @frsyuki

@tagomoris size_t は unsigned だけど、ssize_t は signed なので、ssize_t の方が1ビット短い。

2013-03-15 01:45:34
tagomoris @tagomoris

@tagomoris @frsyuki 自分が間違ってました、なるほどですね > SSIZE_MAX より大きい場合

2013-03-15 01:45:45
Sadayuki Furuhashi @frsyuki

write(2) の返り値が ssize_t だから、そもそも SSIZE_MAX を超えたら途中で帰らないとエラーか正常終了か返り値で区別できなくなるんだな

2013-03-15 01:46:24
tagomoris @tagomoris

@frsyuki まあ、とはいえこれはサイズ指定にまつわる型のミスマッチの問題であって、バッファリング云々とは関係ないすね

2013-03-15 01:46:45
tagomoris @tagomoris

SSIZE_MAX を超えるデータ量の write はblockingであっても全部書かずに戻ることがある、か。うーん。

2013-03-15 01:47:31
Sadayuki Furuhashi @frsyuki

@tagomoris SSIZE_MAX を超えたり、シグナルを受け取ることが想定されるとか、指定バイト数に満たないバイト数で帰ってきたときに発生したエラーを知りたい場合には、writeを繰り返し呼ぶ必要がある…というところでしょうか。

2013-03-15 01:49:45
tagomoris @tagomoris

@frsyuki SSIZE_MAX以上はちょっと特殊な気がするので置いておくと、普通はsignalくらいかなーという気がしますね。その場合はどっちにしろsignal trapがという話で、writeの返り値がcount指定値より少ないときはエラー、でいい気がします。

2013-03-15 01:51:58
tagomoris @tagomoris

と思ったけど、これちがうな

2013-03-15 01:54:47
tagomoris @tagomoris

これ最初 nonblocking write で実装してたからこうなってるんだっけ……もう忘れた

2013-03-15 01:55:16
Sadayuki Furuhashi @frsyuki

@tagomoris signalの扱いはケースバイケースだと思いますが、そうなりますね。もう一回だけsyswriteを呼んで、何が原因で書けなかったかをエラーログに含めるのは親切だと思いました!

2013-03-15 01:55:45
tagomoris @tagomoris

ところで 66000 msg/sec 流れてますよ

2013-03-15 01:57:48
tagomoris @tagomoris

CPUが高クロックでメモリアクセスもだいぶ高速化されてるとはいえ、すごいな

2013-03-15 01:58:30
Sadayuki Furuhashi @frsyuki

仮にシグナル割り込みで write が途中で帰ってきたとして、もう一度 write を読んだら成功してしまうんでは…シグナル割り込みが原因で write が途中で帰ってきたことを知る方法は…?

2013-03-15 01:59:14
tagomoris @tagomoris

@frsyuki あれ、いや、blockingなら途中まで書き込めたバイト数が帰ってくると同時に errno がセットされるんじゃ?

2013-03-15 01:59:46
tagomoris @tagomoris

@frsyuki nonblockingの場合はもう一度 syswrite しないとだめだけど

2013-03-15 02:00:00
Sadayuki Furuhashi @frsyuki

@tagomoris The next write of a non-zero number of bytes would give a failure return (except as noted below) もう一回呼ぶのかと http://t.co/6MJSBrhv36

2013-03-15 02:01:35
tagomoris @tagomoris

"If write() is interrupted by a signal before it writes any data, it shall return -1 with errno set to [EINTR]."

2013-03-15 02:03:30