From: Tanaka Akira Date: 2005-08-03T21:25:04+09:00 Subject: [ruby-dev:26733] Re: [ruby-cvs] ruby/ext/socket, ruby, ruby: * ext/socket/socket.c (ruby_connect): break immediately if a In article <1123025557.870442.14225.nullmailer@x31.priv.netlab.jp>, Yukihiro Matsumoto writes: > |なお、蛇足ですが、Ruby の read でも nonblocking なときにはイベントルー > |プに戻る前にまず read するようにすれば、マルチスレッドでも > |Linux 2.6 の /proc/loadavg を (nonblocking にすれば) 読めるようになっ > |ていいんじゃないかと思います。 > > これは毎回rb_thread_wait_fd()の中でfcntl(fd, F_GETFL, 0)して > チェックするということですかね。コストが問題でなければ > nonblockingであればすぐ返るだけなのですが。 read は EAGAIN で繰り返し呼ばれるますが、select しないでいいのは最初の read だけです。従って、READ_CHECK が適切なんじゃないかと思っています。 rb_thread_wait_fd でそうすると、errno が EAGAIN のときに rb_io_wait_readable が即座に return するようになります。そうすると、 retry: TRAP_BEG; r = read(fptr->fd, fptr->rbuf, fptr->rbuf_capa); TRAP_END; if (r < 0) { if (rb_io_wait_readable(fptr->fd)) goto retry; rb_sys_fail(fptr->path); } のようなコードが busy wait になります。つまり、EAGAIN を受け取った後に は nonblocking だろうが (というか、nonblocking だからこそ) select で待 たなければいけません。 そういえば、失敗すると busy wait になりがちで迷惑だ、というのも nonblocking な挙動を普通のメソッドにとらせたくない理由のひとつですね。 数多くある nonblocking がまきちらす不幸のひとつというか。 あと、コストは迷うところです。毎回やるかフラグを保持するかですが、 nonblocking かどうかというのは他のプロセスと共有されるかもしれないとい うのが問題です。不用意に read してプロセス全体がブロックするのは危険だか らせめて read 直前に読んで critical section を短くしようと考えるか、ど うせ毎回読んでも race condition は残るからフラグにすると考えるか、悩み どころです。 あと、今気がついたんですが、/proc/loadavg は普通のファイル (S_ISREG が 真になるファイル) なんですね。 % ruby -e 'open("/proc/loadavg") {|f| p f.stat.file?}' true とすると、nonblocking かどうかではなく、普通のファイルだったら select しないという判断もできますね。普通のファイルは select すると常に readable になると決まっているので。nonblocking と違ってこっちは変化し ないので、こっちをフラグで保持するのがいいのかなぁ。 まぁ、/proc みたいに怪しげなものに対してどこまでその性質が期待できるか は謎で、select を使って read のブロックを防げる例が発見されることもあ りえなくはないと思いますが。 -- [田中 哲][たなか あきら][Tanaka Akira]