Event driven framework for ruby

Tanaka Akira wrote:

Linux 2.6's select notify readability by a UDP packet with a bad checksum.
But read discards it and waits next packet with a correct checksum if
O_NONBLOCK is clear. If the next packet is not available, the read
hangs. Since O_NONBLOCK avoids the hang, it is possible to care the
problem in application level.

This should be fixed in 2.6.10. They made a workaround that validates the checksum in select for blocking sockets only. See here:

http://linux.bkbits.net:8080/linux-2.6/cset@1.1938.416.3?nav=index.html|src/.|src/net|src/net/ipv4|related/net/ipv4/udp.c

2.4 was also affected and the same fix went into 2.4.29.

Regards,
Ralf

In article <42F996FE.3000702@path.berkeley.edu>,
  Joel VanderWerf <vjoel@path.berkeley.edu> writes:

That post (148436) suggests that the native thread running the
interpreter is not blocked, and the only danger of blocking is in the
*ruby* thread reading the socket. Is that right? A bad UDP packet won't
stop other ruby threads?

Ruby threads is not native threads.
In [ruby-talk:148436], the entire process is not blocked because
O_NONBLOCK is used.

I tried to hang ruby with

  hping2 --udp -p 9999 -b

but the socket did not block.

I can see the entire process blocking with following script.

server% uname -a
Linux nute 2.6.8-2-686 #1 Thu May 19 17:53:30 JST 2005 i686 GNU/Linux
server% ./ruby -rsocket -e '
Thread.new { 1000.times {|i| p i; sleep 1 } }
u = UDPSocket.new; u.bind("0.0.0.0", 2000)
p u.recv(100)'

client% hping2 --udp --count 1 --badcksum --destport 2000 server

···

--
Tanaka Akira

In article <42fbbab1$0$11757$9b4e6d93@newsread4.arcor-online.net>,
  Ralf Horstmann <ralf.horstmann@gmx.de> writes:

This should be fixed in 2.6.10. They made a workaround that validates
the checksum in select for blocking sockets only. See here:

http://linux.bkbits.net:8080/linux-2.6/cset@1.1938.416.3?nav=index.html|src/.|src/net|src/net/ipv4|related/net/ipv4/udp.c

I didn't know that. Thank you.

···

--
Tanaka Akira

Ralf Horstmann wrote:

Tanaka Akira wrote:

Linux 2.6's select notify readability by a UDP packet with a bad
checksum.
But read discards it and waits next packet with a correct checksum if
O_NONBLOCK is clear. If the next packet is not available, the read
hangs. Since O_NONBLOCK avoids the hang, it is possible to care the
problem in application level.

This should be fixed in 2.6.10. They made a workaround that validates
the checksum in select for blocking sockets only. See here:

http://linux.bkbits.net:8080/linux-2.6/cset@1.1938.416.3?nav=index.html|src/.|src/net|src/net/ipv4|related/net/ipv4/udp.c

2.4 was also affected and the same fix went into 2.4.29.

Regards,
Ralf

That's a big relief. Thanks for the information.

···

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Tanaka Akira wrote:

In article <42F996FE.3000702@path.berkeley.edu>,
  Joel VanderWerf <vjoel@path.berkeley.edu> writes:

That post (148436) suggests that the native thread running the
interpreter is not blocked, and the only danger of blocking is in the
*ruby* thread reading the socket. Is that right? A bad UDP packet won't
stop other ruby threads?

Ruby threads is not native threads.
In [ruby-talk:148436], the entire process is not blocked because
O_NONBLOCK is used.

I tried to hang ruby with

hping2 --udp -p 9999 -b

but the socket did not block.

I can see the entire process blocking with following script.

server% uname -a
Linux nute 2.6.8-2-686 #1 Thu May 19 17:53:30 JST 2005 i686 GNU/Linux
server% ./ruby -rsocket -e '
Thread.new { 1000.times {|i| p i; sleep 1 } }
u = UDPSocket.new; u.bind("0.0.0.0", 2000)
p u.recv(100)'

client% hping2 --udp --count 1 --badcksum --destport 2000 server

Hm, it doesn't block for me, but it does exit the ruby process:

$ ruby -rsocket -e '
Thread.new { 1000.times {|i| p i; sleep 1 } }
u = UDPSocket.new; u.bind("0.0.0.0", 2000)
p u.recv(100)'
0
1
2
""
$ uname -a
Linux tumbleweed 2.6.10-5-686 #1 Fri Jun 24 17:33:34 UTC 2005 i686 GNU/Linux
$ ruby -v
ruby 1.8.2 (2004-12-25) [i686-linux]

This is with the same hping2 line:
# /usr/sbin/hping2 --udp --count 1 --badcksum --destport 2000 localhost
HPING localhost (lo 127.0.0.1): udp mode set, 28 headers + 0 data bytes

--- localhost hping statistic ---
1 packets transmitted, 0 packets received, 100% packet loss
round-trip min/avg/max = 0.0/0.0/0.0 ms

···

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Tanaka Akira wrote:

In article <42F996FE.3000702@path.berkeley.edu>,
  Joel VanderWerf <vjoel@path.berkeley.edu> writes:

That post (148436) suggests that the native thread running the
interpreter is not blocked, and the only danger of blocking is in the
*ruby* thread reading the socket. Is that right? A bad UDP packet won't
stop other ruby threads?

Ruby threads is not native threads.
In [ruby-talk:148436], the entire process is not blocked because
O_NONBLOCK is used.

Is there any disadvantage to setting O_NONBLOCK for all UDP packets, as
in [ruby-talk:148436] ? If not, I guess I'll just do that to be safe...

(I'm assuming the MAC layer on our radios doesn't do its own
checksumming. If it does, this might not be a problem.)

···

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Joel VanderWerf wrote:

Hm, it doesn't block for me, but it does exit the ruby process:

...which means the packet was received normally by the UDP port.

Maybe a difference between 2.6.8 and 2.6.10?

···

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

In article <42F9A0C2.7000905@path.berkeley.edu>,
  Joel VanderWerf <vjoel@path.berkeley.edu> writes:

Hm, it doesn't block for me, but it does exit the ruby process:

I can reproduce the exit if server and client is same machine.

It seems that the block is only occur if server and client is
different machine.

···

--
Tanaka Akira

In article <42F9A50C.4010806@path.berkeley.edu>,
  Joel VanderWerf <vjoel@path.berkeley.edu> writes:

Is there any disadvantage to setting O_NONBLOCK for all UDP packets, as
in [ruby-talk:148436] ? If not, I guess I'll just do that to be safe...

Some methods may behave differently. At least IO#sysread raises
EAGAIN instead of blocking in single thread mode. I'm not sure about
other methods.

···

--
Tanaka Akira

Is there any disadvantage to setting O_NONBLOCK for all UDP packets, as
in [ruby-talk:148436] ? If not, I guess I'll just do that to be safe...

On Linux, I've had to use a timeout { } to get around the
process blocking on a UDP recv.

Regards,

Bill

···

From: "Joel VanderWerf" <vjoel@path.berkeley.edu>