From: Sam Duncan Date: 2011-12-14T06:46:12+09:00 Subject: Re: Fixing Net::TFTP On 14/12/11 05:20, Reid Wightman wrote: > Sam Duncan wrote in post #1036445: > >> What happens if you set non-blocking on the socket and try to catch an >> exception on the recv? >> >> require 'fcntl' >> ... >> >> s = UDPSocket.new >> >> s.fcntl(Fcntl::F_SETFL, s.fcntl(Fcntl::F_GETFL) | Fcntl::O_NONBLOCK) >> ... >> begin >> >> packet, from = s.recvfrom(2048,0) >> >> rescue StandardError => e >> puts "Waarg: #{e}" >> next >> end >> ... >> > Hi Sam - > > Thanks for the help. > > I am confused, because my program still blocks on the call to > s.recvfrom(). I tossed a puts before and after the 's.recvfrom()' call > and sure enough, it is still pausing for 5 seconds inside of the try > block. This in spite of the O_NONBLOCK. And for sanity I did a few > other printy things to be sure that my program is using the modified > version of the library. > > Is there any known goofiness to ruby 1.8.7's IO not working correctly? > The behavior that I'm seeing seems really...odd. > > Thanks again, > Reid And you said that changing the recv buffer size (2**16) made no difference? How about specifying Socket::MSG_TRUNC in the flags to see if the whole datagram didn't make it (man recv(2)/ recvfrom(2))? Or maybe try reading the header (I read it is four bytes) to find the data length and then a subsequent read for the rest based on that? Sorry, I'm clutching at straws, but I'm curious to see what you find. I found some old forum posts with people discussing non-blocking UPD sockets in Ruby, but they gave up and used event machine before the issue was resolved which is a shame. Looking at s_recvfrom and s_recvfrom_nonblock in socket.c the main difference appears to be that the non-block version sets MSG_DONTWAIT if defined, and then uses rb_io_set_nonblock from io.c to do the fcntl shuffle. The blocking version has a retry loop which sits in rb_io_wait_readable on the socket fd. I would definitely use the nonblock one when fiddling around just to rule out ever getting into that rb_io_wait_readable which is just another select. For what it is worth, neither of those functions appear to have changed between ruby-1.8.6-p420, ruby-1.8.7-p352, and ruby-1.9.3-p0. Sam