# Puzzled about Ruby's behaviour re. closed sockets

**URL:** <https://www.ruby-forum.com/t/puzzled-about-rubys-behaviour-re-closed-sockets/110687>\
**Category:** Ruby\
**Created:** [July 29, 2007, 5:05pm UTC](https://www.ruby-forum.com/t/puzzled-about-rubys-behaviour-re-closed-sockets/110687 "2007-07-29T17:05:37Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![bizot](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/58956e/32.png) [@bizot](https://www.ruby-forum.com/u/bizot)\
**Post date:** [July 29, 2007, 5:05pm UTC](https://www.ruby-forum.com/t/puzzled-about-rubys-behaviour-re-closed-sockets/110687/1 "2007-07-29T17:05:37Z")

</div>

Everyone,

I’d like to write a test that ensures a Server application correctly  
handles closed client connections – more specifically: I want to set  
up a TCPServer, then a client, then close the client, then attempt to  
write on the client Connection from server side – and make sure no  
Error gets fired.

To my great surprise, the test doesn’t behave in any predictible way  
– sometimes it passes, sometimes it fails.

# I’ve written a piece of code that illustrates it:

require ‘socket’

consecutive\_puts\_to\_attempt = 1  
ok\_counter = 0  
error\_counter = 0

10000.times do  
server = TCPServer.open ‘127.0.0.1’, 4807  
client = TCPSocket.open ‘127.0.0.1’, 4807  
connection = server.accept  
client.close

begin  
consecutive\_puts\_to\_attempt.times {connection.puts “Hello!”}  
ok\_counter += 1  
rescue  
error\_counter += 1  
end  
server.close  
end

# puts “(Unexpectedly) passed #{ok\_counter} times;” puts “(correctly) failed #{error\_counter} times.”

Statistically, this piece of code unexpectedly passes with no raised  
error about 98% of the time. Errors are Errno::EPIPE and  
Errno::ECONNRESET

When I fiddle with consecutive\_puts\_to\_attempt value, the number of  
expected raised errors changes –

puts attempts chances of raised error  
1 2%  
2 98%  
3 98.5%  
4 99%

Here is my environment:  
ruby -v

> ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-darwin8.10.1]

Any idea of what’s going on?  
Any suggestion about how I could make this piece of code predictible?  
– Emmanuel.

---

<div class="post-metadata">

**Author:** ![bizot](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/58956e/32.png) [@bizot](https://www.ruby-forum.com/u/bizot)\
**Post date:** [July 30, 2007, 9:59am UTC](https://www.ruby-forum.com/t/puzzled-about-rubys-behaviour-re-closed-sockets/110687/2 "2007-07-30T09:59:05Z")

</div>

2007/7/29, Emmanuel G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> I’d like to write a test that ensures a Server application correctly  
> handles closed client connections – more specifically: I want to set  
> up a TCPServer, then a client, then close the client, then attempt to  
> write on the client Connection from server side – and make sure no  
> Error gets fired.
> 
> To my great surprise, the test doesn’t behave in any predictible way  
> – sometimes it passes, sometimes it fails.

> Any idea of what’s going on?  
> Any suggestion about how I could make this piece of code predictible?

I guess it’s a combination of timing and buffering issue. With a  
modified version I get

RKlemme@padrklemme1 ~  
$ ruby ruby/socket-test-1.rb  
(Unexpectedly) passed 2 times;  
{Errno::ECONNABORTED=\>998}

(see attachment)

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![bizot](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/58956e/32.png) [@bizot](https://www.ruby-forum.com/u/bizot)\
**Post date:** [July 31, 2007, 11:26am UTC](https://www.ruby-forum.com/t/puzzled-about-rubys-behaviour-re-closed-sockets/110687/3 "2007-07-31T11:26:08Z")

</div>

Robert,

Thanks for your answer.

> With a modified version I get
> 
> (Unexpectedly) passed 2 times;  
> {Errno::ECONNABORTED=\>998}

## I’ve tried your modified version. Here is a typical output when attempting once to write in the closed pipe :

## (Unexpectedly) passed 960 times; {Errno::EPIPE=\>38, Errno::ECONNRESET=\>2}

## … this to be compared with typical output when attempting to write 6th times in a row in the closed pipe :

## (Unexpectedly) passed 4 times; {Errno::EPIPE=\>987, Errno::ECONNRESET=\>9}

Strangely enough, I don’t seem to get any Errno::ECONNABORTED ever.

> I guess it’s a combination of timing and buffering issue.

I’ve reached the same conclusion – which brings me to the question:  
what can I do to make the combination of timing and buffering  
predictible? Or how may I get around it?

– Emmanuel.
