Forum: Ruby Puzzled about Ruby's behaviour re. closed sockets

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
7c44b2be264aff1bdec45c6a4bc3b041?d=identicon&s=25 Emmanuel Gaillot (Guest)
on 2007-07-29 17:05
(Received via mailing list)
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.
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2007-07-30 09:59
(Received via mailing list)
Attachment: socket-test-1.rb (547 Bytes)
2007/7/29, Emmanuel Gaillot <emmanuel.gaillot@gmail.com>:
> 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
7c44b2be264aff1bdec45c6a4bc3b041?d=identicon&s=25 Emmanuel Gaillot (Guest)
on 2007-07-31 11:26
(Received via mailing list)
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.
This topic is locked and can not be replied to.