[#35446] [Ruby 1.9 - Bug #4477][Open] Kernel:exec and backtick (`) don't work for certain system commands — Joachim Wuttke <j.wuttke@...>

10 messages 2011/03/07

[#35476] [Ruby 1.9 - Bug #4489][Open] [PATCH] Encodings with /-(unix|dos|mac)\Z/ — "James M. Lawrence" <quixoticsycophant@...>

20 messages 2011/03/10

[#35552] [Ruby 1.9 - Feature #4523][Open] Kernel#require to return the path of the loaded file — Alex Young <alex@...>

14 messages 2011/03/24

[#35565] [Ruby 1.9 - Feature #4531][Open] [PATCH 0/7] use poll() instead of select() in certain cases — Eric Wong <normalperson@...>

33 messages 2011/03/28

[#35566] [Ruby 1.9 - Feature #4532][Open] [PATCH] add IO#pread and IO#pwrite methods — Eric Wong <normalperson@...>

12 messages 2011/03/28

[#35586] [Ruby 1.9 - Feature #4538][Open] [PATCH (cleanup)] avoid unnecessary select() calls before doing I/O — Eric Wong <normalperson@...>

9 messages 2011/03/29

[ruby-core:35506] Re: TCPServer internals - chasing EBADF error

From: Marcus Rueckert <darix@...>
Date: 2011-03-16 11:32:06 UTC
List: ruby-core #35506
On 2011-03-16 19:57:30 +0900, Xavier Shay wrote:
> The following code intermittently raises an EBADF error and I am
> trying to figure out why.
> 
>     require 'socket'
>     8.times do
>       fork do
>         1000.times do
>           sleep (rand / 1000.0)
>           begin
>             server = TCPServer.new('127.0.0.1', 5678)
>             server.close
>           rescue Errno::EADDRINUSE => e
>           end
>         end
>       end
>     end
> 
> I am running on an 8 core ubuntu machine with ruby 1.9.2.
> I have been reading through the ruby source and here is what I have
> discovered:
> - TCPServer.new ends up calling init_inetsock_internal in
> ext/socket/tcpsocket.c, which calls socket(2) and bind(2) to create
> a socket
> - EBADF is one of bind's documented errors, and can be caused by
> binding to a closed socket
> (http://www.gnu.org/s/libc/manual/html_node/Error-Codes.html)
> 
> From that I have two hypotheses:
> 1) socket is called at the same time 2 processes, returning the same
> FD. It is closed by one process before the other binds.
> 2) socket picks up a FD that has been "closed" by ruby but not quite
> "closed" properly by the OS, and tries to bind to it.
> 
> I am at a bit of a loss as to where to go next. I was trying to
> track down IO#close which led me to rb_io_close in io.c - I can't
> quite figure out how this actually closes the socket (I was
> expecting a system call to close). It leads to thread_fd_close_i in
> thread.c and I can't figure what this is doing either.
> 
> Can anyone shed some light?

smells like a race condition.

    darix

-- 
           openSUSE - SUSE Linux is my linux
               openSUSE is good for you
                   www.opensuse.org

In This Thread