From: Brian Candler Date: 2007-08-28T18:01:33+09:00 Subject: Re: UDP sockets raise exception on MIPS platform On Tue, Aug 14, 2007 at 06:07:01PM +0900, Brian Candler wrote: > I am running ruby-1.8.6 under OpenWrt (*), which is a small MIPS platform > (4MB flash, 16MB RAM) running linux-2.4.34 and uClibc. > > Everything seems to work fine apart from UDP sockets. As soon as you try to > read using 'recvfrom', an exception is raised: > > root@OpenWrt:~# irb > irb(main):001:0> require 'socket' > => true > irb(main):002:0> s = UDPSocket.new > => # > irb(main):003:0> s.bind("0.0.0.0",1234) > => 0 > irb(main):004:0> d = s.recvfrom(512) > IOError: recv for buffered IO > from (irb):4:in `recvfrom' > from (irb):4 > irb(main):005:0> > > But strangely, TCP sockets work just fine. > > Now, the only place I can see this exception raised is here in > etc/socket/socket.c: > > if (rb_read_pending(fptr->f)) { > rb_raise(rb_eIOError, "recv for buffered IO"); > } I have narrowed the problem down further to this line in io.c: # define READ_DATA_PENDING(fp) (!feof(fp)) With a FILE* wrapping a UDP socket, feof() always returns zero. This can be demonstrated with the following test program: ---- 8< ---- #include #include #include #include #include #include int main(void) { int s; FILE *f1, *f2; /* udp_init */ s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { perror("socket"); exit(1); } /* init_sock / rb_fdopen */ f1 = fdopen(s, "r"); if (!f1) { perror("fdopen r"); exit(1); } f2 = fdopen(s, "w"); if (!f2) { perror("fdopen w"); exit(1); } printf("feof(f1)=%d\n", (int)feof(f1)); printf("feof(f2)=%d\n", (int)feof(f2)); return 0; } ---- 8< ---- When I run it either on the OpenWrt target or a normal i386 Linux system, I get feof(f1)=0 feof(f2)=0 Now, when building Ruby under OpenWrt, the READ_DATA_PENDING macro is defined as !feof() as shown above - and as a result, whenever you try to call recvfrom on a UDP socket, you get an exception raised here in ext/socket/socket.c: if (rb_read_pending(fptr->f)) { rb_raise(rb_eIOError, "recv for buffered IO"); } So my question is, what's the "right" way to fix this problem? Should I just comment out these three lines when building under OpenWrt? Would there be any undesired side-effects of this? Thanks, Brian.