TCPSocket.new blocks other threads

C

christoph.heindl

hi,

when trying to connect to an ip address, from within a thread, that
does not exist, using TCPSocket.new(ip, port), it seems that other
threads are blocked until the connection has timed out. This hangs the
entire application for about 20secs.
However i have only noticed this behaviour in windows XP (propably
others too).

Any known workarounds?

I tried to find some information on nonblocking io (sockets) with ruby,
but i gave up,
after googling for around an hour..any links would be appreciated
christoph
 
R

Robert Klemme

hi,

when trying to connect to an ip address, from within a thread, that
does not exist, using TCPSocket.new(ip, port), it seems that other
threads are blocked until the connection has timed out. This hangs the
entire application for about 20secs.
However i have only noticed this behaviour in windows XP (propably
others too).

Any known workarounds?

I tried to find some information on nonblocking io (sockets) with ruby,
but i gave up,
after googling for around an hour..any links would be appreciated
christoph

Just a faint hint: I remember having seen something similar some days (or
maybe weeks) ago that also involved XP. Can't remember the resolution
though. Maybe you just check with ruby-talk.

Kind regards

robert
 
M

martinus

This is a serious problem! Try this code without an internet
connection:

Thread.new {
sleep 1
TCPSocket.new("xxx.nonexisting.xxx", 1234)
}

loop {
puts "."
sleep 0.25
}

This should continuously print a ".", but after 1 second this blocks
Ruby completely.

martinus
 
V

Ville Mattila

martinus said:
This is a serious problem! Try this code without an internet
connection:

Thread.new {
sleep 1
TCPSocket.new("xxx.nonexisting.xxx", 1234)
}

loop {
puts "."
sleep 0.25
}

This should continuously print a ".", but after 1 second this blocks
Ruby completely.
Works ok with
ruby -v
ruby 1.8.2 (2005-01-23) [sparc-solaris2.8]

and

ruby -v
ruby 1.8.2 (2004-07-29) [i386-mswin32]

So this might be problem on your OS.

- Ville
 
E

Eric Hodel

--Apple-Mail-48--600429779
Content-Transfer-Encoding: 7bit
Content-Type: text/plain; charset=US-ASCII; format=flowed

This is a serious problem! Try this code without an internet
connection:

Thread.new {
sleep 1
TCPSocket.new("xxx.nonexisting.xxx", 1234)
^^^^^^^^^^^^^^^^^^^^^

With Thread.abort_on_exception = true

causes:

getaddrinfo: No address associated with nodename (SocketError)

after 1 second.

So this is not a TCPSocket-specific problem, but a DNS resolver
problem, probably due to your OS' DNS resolver library performing a
blocking call of some kind. There's nothing Ruby can do about this,
unless your system provides a non-blocking DNS resolver API.

Changing it to a non-local IP address with no network connection causes:

No route to host - connect(2) (Errno::EHOSTUNREACH)

after 1 second.

Adding a network connection causes it to print . until the network
connection times out on:

ruby 1.8.2 (2004-12-25) [powerpc-darwin7.7.0]

--
Eric Hodel - (e-mail address removed) - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

--Apple-Mail-48--600429779
content-type: application/pgp-signature; x-mac-type=70674453;
name=PGP.sig
content-description: This is a digitally signed message part
content-disposition: inline; filename=PGP.sig
content-transfer-encoding: 7bit

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (Darwin)

iD8DBQFB9LONMypVHHlsnwQRAnHyAKCUg9cuWceYdP57emmeM7DvvFu0xgCdEpyq
tbvgHG74hs6wkvgrF+PbMf0=
=BCYn
-----END PGP SIGNATURE-----

--Apple-Mail-48--600429779--
 
M

martinus

Sorry, I made a mistake in my sample. This is correct:

require "socket"
Thread.abort_on_exception= true

Thread.new {
sleep 1
begin
TCPSocket.new("xxx.nonexisting.xxx", 1234)
rescue
end
puts "done"
}

loop {
puts "."
sleep 0.25
}
 
C

christoph.heindl

well actually it does work.
but try changing the from "xxx.nonexisting.xxx" to a ip address which
cannot be reached.eg 192.168.0.43

then it will block...
 
A

Artur Merke

Hi,

I recently discovered, that my gallery generating script
was generating twice as large pics as in the runs I made
some months ago (in between I made some Debian unstable upgrade
sessions, but the problem may not be Debian specific)

After a while I found out, that if

vga.write("pic.jpg")

is replaced by

vga.write("pic.jpg"){ self.quality = 75 }

then the problem doesn't occur. Therefore the compression
quality seems no longer to be 75% by default ...
 
C

christoph.heindl

thanks for your reply.
however, as i pointed out in my initial post, the problem only occurs
on windows. I searched for the problem for quite a while and it seems
that ruby uses Winsock on Windows (instead of Winsock2). Somehow ruby's
scheduler seems not to be able to schedule other threads during a
TCPSocket connection attempt. I think this is not a ruby problem in
general, but has todo with ruby + winsock.
Maybe there are any patches around?
 
V

Ville Mattila

thanks for your reply.
however, as i pointed out in my initial post, the problem only occurs
on windows. I searched for the problem for quite a while and it seems
that ruby uses Winsock on Windows (instead of Winsock2). Somehow ruby's
scheduler seems not to be able to schedule other threads during a
TCPSocket connection attempt. I think this is not a ruby problem in
general, but has todo with ruby + winsock.
Maybe there are any patches around?

Hello, works fine with me (windows 2000 + SP4 and all security patches)
....
type foo.rb
require "socket"
Thread.abort_on_exception= true

Thread.new {
sleep 1
begin
TCPSocket.new("xxx.nonexisting.xxx", 1234)
rescue
end
puts "done"
}

loop {
puts "."
sleep 0.25
}

c:\data\ruby\bin\ruby -v foo.rb
ruby 1.8.2 (2005-01-19) [i386-mswin32]
..
..
..
..
done
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
..
foo.rb:16:in `sleep': Interrupt
from foo.rb:16
from foo.rb:14:in `loop'
from foo.rb:14

- Ville
 
C

christoph.heindl

thanks for your reply Ville.

I'm just curious, but have you tried to use an ip address instead of
"xxx.nonexisting.xxx". E.g 192.168.0.5 (if 192.168.0.5 is not
reachable).
I have only windows xp systems around, maybe it turns out to be a
windows xp problem?
 
P

Piergiuliano Bossi

Hello Cristoph, I can pragmatically confirm what Eero was saying.

The following script works fine on Win2K SP4.

C:\tmp>type sock.rb
require "socket"
Thread.abort_on_exception= true

Thread.new {
sleep 1
begin
TCPSocket.new("192.168.111.222", 1234)
rescue
end
puts "done"
}

loop {
puts "."
sleep 0.25
}
C:\tmp>ruby -v sock.rb
ruby 1.8.2 (2004-11-06) [i386-mswin32]
..
..
..
..
done
..
..
..
..
..
..
..
..
..
..
..
..
..
sock.rb:15:in `sleep': Interrupt from sock.rb:15
from sock.rb:13:in `loop'
from sock.rb:13

No hangs at all, it runs smoothly if I am disconnected from the network,
but if I connect my address is in the form 192.168.xxx.yyy ==>
re-executing the same script it hangs before writing "done" and then it
writes "done" when timeout occurs (20 seconds in my case).

Ciao, Giuliano
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top