From: "Christoffer Lernö" Date: 2007-10-15T00:09:32+09:00 Subject: Re: write_nonblock is blocking? On 14 Oct 2007, at 09:58, Eric Hodel wrote: > On Oct 14, 2007, at 24:13 , Christoffer Lernö wrote: >> On 14 Oct 2007, at 01:23, Eric Hodel wrote: >>> On Oct 13, 2007, at 14:55 , Christoffer Lernö wrote: >>>> Anyone know what's up with TCPSocket#write_noblock actually >>>> blocking when sending a packet that exceeds the buffer size of >>>> the socket in 1.8.6 on Mac. >>>> >>>> The behaviour seems slightly counter-productive. >>> >>> How long does it block? I see ruby occasionally being delayed >>> 10ms when using write_nonblock, but not repeatably for the same >>> packet sizes. Probably my benchmark script is wrong. >>> >>> Could you supply a benchmark script that illustrates your problem? >>> >>> #write_nonblock first does rb_io_check_closed() which might call >>> down to fseek(3) then write(2) before calling rb_io_set_nonblock >>> (). I'm not even close to being a sockets expert though, I just >>> read the man pages. >> >> Thanks. Know it "should work" made me try to analyze the >> situation. Here is an example code: >> >> [...] >> >> It looks like write_nonblock together with accept_nonblock causes >> some issues. >> >> Now I could be using these wrong as both are new (in 1.8.6?) > > I couldn't reproduce with your this test using: > > $ ruby -v > ruby 1.8.6 (2007-09-23 patchlevel 5000) [powerpc-darwin8.10.0] > > I'll to try again tomorrow though, since I'm tired. > > I experimented a bit with your benchmark, and found that writing a > large string would only write as much as the socket buffer would > accept (81660 bytes, in my case). > > Maybe you need to set the TCP_NODELAY socket option? > > socket.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1 > > I once made write_nonblock raise Errno::EAGAIN, but I accidentally > deleted that change. I'll play some more tomorrow when I'm not so > tired. Could this be due to me running ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-darwin8.10.1] ? The funny thing was that only the socket returned by accept_nonblock had this behaviour, that is require 'socket' a = TCPServer.new(5000) socket = TCPSocket.new("localhost", 5000) other = a.accept puts "Start Write" other.write_nonblock("X" * 300000) puts "End Write" Works. require 'socket' a = TCPServer.new(5000) socket = TCPSocket.new("localhost", 5000) other = a.accept_nonblock puts "Start Write" other.write_nonblock("X" * 300000) puts "End Write" Doesn't work. What's so special about a socket returned by accept_nonblock? /Christoffer