In article <1123025557.870442.14225.nullmailer / x31.priv.netlab.jp>,
  Yukihiro Matsumoto <matz / ruby-lang.org> 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]