# Sockets and threads

**URL:** <https://www.ruby-forum.com/t/sockets-and-threads/56464>\
**Category:** Ruby\
**Created:** [March 31, 2006, 1:40pm UTC](https://www.ruby-forum.com/t/sockets-and-threads/56464 "2006-03-31T13:40:06Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Dominik\_Werder](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/dfb087/32.png) [@Dominik\_Werder](https://www.ruby-forum.com/u/Dominik_Werder)\
**Post date:** [March 31, 2006, 1:40pm UTC](https://www.ruby-forum.com/t/sockets-and-threads/56464/1 "2006-03-31T13:40:06Z")

</div>

Hello,

I observed that even if every thread in a program creates it’s own  
Socket, but all to the same Server, then this is not thread-safe.

It is the same situation as if every thread shared the same Socket  
without any mutexes. I observed this with TCPSockets, UNIXSockets ans  
UDPSockets.

I run Kernel 2.6.14.2, ruby 1.8.4 (2005-12-24) [i686-linux]

The short source code below produces the following output on the server.  
If I enabled the mutex (the 3 lines commented out) it would work better.

Got: thread[16] says 65  
Got: thread[19] says 68thread[17] says 20  
Got:  
Got: thread[24] says 97  
Got: thread[8] says 64thread[26] says 17thread[13] says 43  
Got:  
Got:  
Got: thread[7] says 84  
Got: thread[0] says 78thread[18] says 37  
Got: thread[27] says 98  
Got:  
Got: thread[18] says 13  
Got: thread[11] says 19  
Got: thread[1] says 91thread[26] says 18  
Got:  
Got: thread[1] says 53  
Got: thread[19] says 42

# First start the server with:

# ruby tcpsockets.rb server

# Then start the client which spawns several threads:

# ruby tcpsockets.rb

require ‘socket’  
require ‘monitor’

if ARGV[0] == ‘server’  
threads = []  
server = TCPServer.new ‘localhost’, 8889  
putslock = Monitor.new  
while socket = server.accept  
t = Thread.new(socket) do |sock|  
while str = sock.gets  
putslock.synchronize do  
puts “Got: #{str}”  
end  
end  
end  
threads \<\< t  
end  
threads.each do |t| t.join end  
else  
Thread.abort\_on\_exception = true  
#socketlock = Monitor.new  
threads = []  
30.times do |i|  
t = Thread.new(i) do |ii|  
count = 0  
socket = TCPSocket.new ‘localhost’, 8889  
puts “Using socket #{socket.object\_id}”  
while count \< 10  
#socketlock.synchronize do  
socket.puts “thread[#{ii}] says #{Kernel.rand 100}”  
socket.flush  
#end  
sleep Kernel.rand \* 0.3  
count += 1  
end  
end  
threads \<\< t  
end  
threads.each do |t| t.join end  
end

Is this known/intended behavior?

thanks and a good day!  
Dominik

---

<div class="post-metadata">

**Author:** ![Dominik\_Werder](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/dfb087/32.png) [@Dominik\_Werder](https://www.ruby-forum.com/u/Dominik_Werder)\
**Post date:** [March 31, 2006, 2:26pm UTC](https://www.ruby-forum.com/t/sockets-and-threads/56464/2 "2006-03-31T14:26:13Z")

</div>

Hello,

I found the bug: In the client code the variable “socket” was already  
known to the interpreter, but anyway not in the same scope, so every  
thread overwrote the socket and in the end all used the same  
connection…

I didn’t know that

if false  
yo = 123  
else  
puts yo.class.name  
end

would output “NilClass”…

bye!  
Dominik

---

<div class="post-metadata">

**Author:** ![Dominik\_Werder](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/dfb087/32.png) [@Dominik\_Werder](https://www.ruby-forum.com/u/Dominik_Werder)\
**Post date:** [March 31, 2006, 11:40pm UTC](https://www.ruby-forum.com/t/sockets-and-threads/56464/3 "2006-03-31T23:40:57Z")

</div>

Dominik Werder wrote:

> else  
> puts yo.class.name  
> end
> 
> would output “NilClass”…

I’m getting more and more defensive about this kind of bug. I usually  
just do

Thread.new(…) { |…| some\_method(…)}

and then I can code some\_method without worrying about local variable  
sharing.

Another example is when threads are created in a loop. Even if the  
thread code is very small, local vars with shared binding can be  
devastating:

a = []  
i = 0  
(0…100).map do  
Thread.new {sleep 0.001; a \<\< i}  
i += 1  
end  
sleep 1  
p a.uniq.size

Output is unpredictable, 74, 86, etc. (YMMV)

Obviously, this could be solved by making i local to the block, or  
passing it to Thread.new. Without the sleep 0.001, I don’t seem to get  
this behavior (the output is 100), but I wouldn’t rely on that: the ruby  
thread scheduler could still reasonably schedule threads so that two or  
more of them saw the same value of i. So it’s still best to pass  
arguments to Thread.new.
