2008/3/27, Marcelo <marcelo.magallon / gmail.com>:
>  I don't know what GServer is, but I guess that serve is called when
>   there's a connection.  As John points out, if io.eof? is true, select
>   will return immediately.  For example:
>
>  #!/usr/bin/env ruby
>
>  loop do
>     open("fifo") do |f|
>         puts "Opened fifo"
>         loop do
>             ready, = select([f], nil, nil, nil).first
>             break if ready.nil?
>             p ready.read(1000)
>             break if ready.eof?
>         end
>     end
>     puts "Closed fifo"
>  end
>
>   You'll see that it opens the fifo, blocks on it, once you write to it
>   select returns, and once you reach EOF the inner loop breaks and the
>   fifo is closed.  You can do something like:
>
>   $ ruby -e 'puts "x"*2000' > fifo
>
>   and you'll see the inner loop consuming all the input.
>
>   If you remove:
>
>             break if ready.eof?
>
>   you'll see the behaviour you describe.

I've tested your code and I understand it now.
The problem is if I use GServer. I've done a very simple example code:

Your code a little modified:


--- io1.rb --------------
#!/usr/bin/env ruby

loop do
    puts "----- main loop -----"
    open("fifo") do |f|
        puts "Opened fifo"
        loop do
            p "-- second loop --"
            ready, = select([f], nil, nil, nil).first
            break if ready.nil?
            p ready.read(10)
            break if ready.eof?
        end
    end
    puts "Closed fifo"
end
--------------------

Now I do:

~# ./io1.rb
----- main loop -----

(and waits)

~# ruby -e 'puts "X_"*2' > fifo
Opened fifo
"-- second loop --"
"XX\n"
Closed fifo
----- main loop -----

(and waits again).

Perfect.


But now I try a similar way using GServer (that implements a TCP
multithreaded server):

----------- io2.rb ----------------
#!/usr/bin/env ruby

require 'gserver'


class Server < GServer

        def initialize(port=2000)
                super(port)
        end

        def serve(io)

                puts "------------ serve(io) -------------"
                loop do
                        p "-- second loop --"
                        ready, = select([io], nil, nil, nil).first
                        break if ready.nil?
                        p ready.read(10)
                        break if ready.eof?
                end
                puts "---------- end server(io) ------------"
        end

end

server = Server.new
server.audit=true
server.start

loop do
        #puts "----- main loop -----"
        break if server.stopped?
end
-------------------------------------


~# ./io2.rb
----- main loop -----
----- main loop -----
----- main loop -----
----- main loop -----
...

So there is no connection yet but Ruby is doing a loop and eating 90%
of CPU. Why??

I connect:

~# echo "12345678901234567890QWERTYUIOP" | nc 127.0.0.1 2000   (and
press Ctrl +C):
------------ serve(io) -------------
"-- second loop --"
"1234567890"
"-- second loop --"
"1234567890"
"-- second loop --"
"QWERTYUIOP"
"-- second loop --"
"\n"
---------- end server(io) ------------
[Thu Mar 27 10:48:50 2008] Server 127.0.0.1:2000 client:44187 disconnect



>   Short answer: are you sure serve is called only if there's a connection?

Yes, "puts ---------server(io) ----------" confirms it.


I will try to do the same without GServer or threads, using TCPServer
class and so.



-- 
IƱaki Baz Castillo
<ibc / aliax.net>