From: Tanaka Akira Date: 2005-07-17T12:30:11+09:00 Subject: Re: Nonblocking Sockets In article <01a001c58a52$13828780$6442a8c0@musicbox>, "Bill Kelly" writes: > I tend to re-issue the nonblock fcntl() call before > every socket operation I perform. > > Even so, I *still* hit this timeout occasionally: > > if select([sock], nil, nil, UDP_RECV_TIMEOUT) > begin > timeout(UDP_RECV_TIMEOUT) { > sock.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK) if defined? Fcntl::O_NONBLOCK > resp = sock.recvfrom(65536) > } > rescue Timeout::Error > $stderr.puts "Timeout::Error in sock.recvfrom !" > end > end > > ...Since select() said data was ready, AND since I'm > requesting a nonblocking operation... I have no idea > why #recvfrom sometimes hangs. Hmm. Linux, UDP, readable by select, not readable by recvfrom. It may be caused by wrong UDP checksum. Linux-Kernel Archive: UDP recvmsg blocks after select(), 2.6 bug? http://www.ussg.iu.edu/hypermail/linux/kernel/0410.0/1372.html Debian Bug report logs - #275585 - /usr/sbin/inetd: UDP builtins can be used to hang inetd http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=275585&archive=yes select(2): Under Linux, select may report a socket file descriptor as "ready for reading", while nevertheless a subsequent read blocks. This could for example happen when data has arrived but upon examination has wrong checksum and is discarded. There may be other circumstances. Thus it may be safer to use O_NONBLOCK on sockets that should not block. You can test UDP with wrong checksum by hping2. See the debian bug report #275585. > It used to totally hang > my program (on linux), indefinitely, about once a day, > until I added the timeout(). It seems that Ruby process doesn't hang because timeout works. timeout is implemented by Ruby thread. So your problem is IPSocket#recvfrom retry when EAGAIN. You may need lower level method which makes EAGAIN user visible. -- Tanaka Akira