TCPSocket.new blocks other threads

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

<christoph.heindl@gmail.com> schrieb im Newsbeitrag news:1106498039.209351.9940@f14g2000cwb.googlegroups.com...

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

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

robert,

i could not find any information in ruby-talk...
:frowning:

christoph

"martinus" <martin.ankerl@gmail.com> writes:

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

^^^^^^^^^^^^^^^^^^^^^

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]

PGP.sig (186 Bytes)

···

On 24 Jan 2005, at 00:05, martinus wrote:

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

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

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

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
}

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...

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?

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 ...

···

--

Artur

"christoph.heindl@gmail.com" <christoph.heindl@gmail.com> writes:

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

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?

Artur Merke wrote:

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

According to http://www.imagemagick.org/www/ImageMagick.html#options the
default quality is still 75. It's possible the version of ImageMagick you
have has a bug. The current version is 6.1.9-3.

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

···

christoph.heindl@gmail.com wrote:

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?

--
If you want to send me an email address should be 'p', then a dot,
followed by 'bossi' at 'quinary', another dot and 'com' at last