KOSAKI Motohiro <kosaki.motohiro / gmail.com> wrote:
> > KOSAKI Motohiro <kosaki.motohiro / gmail.com> wrote:
> >> > Issue #4558 has been updated by Eric Wong.
> following scenario should be happen too.
> 
> CPU1                    CPU2                    CPU3
> -------------------------------------------------------------------
> open() -> 5
>                              close(5)
>                                                          open() -> 5
> read(5) -> success, but read different data.

OK, I'm starting to think there's no safe way to handle these
situations, especially with MVM on the horizon.  Just telling users to
stop doing close() in a different thread is probably the best way to
go...

> >> Hmm...
> >> If windows can't implement close() case, I doubt r30852 is correct fix.
> >> Is this really worth that *nix and windows have different spec?
> >
> > If r30852 is reverted, Linux (and maybe other *nix) will still break
> > threads out of blocking read/write with EBADF and
> > rb_io_wait_*able(fptr->fd) will raise IOError as long as we
> > assign fptr->fd = -1 before the actual close() call in IO#close.
> >
> > Maybe Windows (and possibly other OS) will be forced to call do_select()
> > to implement behavior consistent with Linux.
> 
> ???
> I'm sorry, I haven't catch your point.
> Which issue is solved by calling do_select()?

It can reduce the likelyhood of read() being uninterruptable since
do_select() will sleep in 100ms intervals to check for interrupts on
win.  There's still a small chance of blocking read() since select()
can have false positives and other threads could've drained the data...

> > On a related note, r30852 also has the problem with making IO#close an
> > O(n) operation since it needs to scan through all threads (and I'd like
> > to run thousands of threads :>).
> 
> I have no opinion. I like faster software, but I haven't seen close
> makes performance bottleneck.

Contrived test case, but it gets worse as nr_thread increases:

# ruby 1.9.2p180 (2011-02-18 revision 30909) [x86_64-linux]
  0.010000   0.000000   0.010000 (  0.007288)

# ruby 1.9.3dev (2011-04-14 trunk 31267) [x86_64-linux]
  0.030000   0.000000   0.030000 (  0.033881)
-----------------------------8< -------------------------
require "benchmark"
nr_thread = 1_000
nr_close = 1_000

threads = nr_thread.times.map { Thread.new { sleep } }
puts(Benchmark.measure do
  nr_close.times do
    File.open(__FILE__).close
  end
end)
threads.each { |thr| thr.run }.each { |thr| thr.join }
-- 
Eric Wong