[ 
https://issues.apache.org/jira/browse/THRIFT-171?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12640670#action_12640670
 ] 

Dave Dupre commented on THRIFT-171:
-----------------------------------

I've been playing with this for a bit, and I can make it happen now in an all 
Ruby env. I attempted to use a more threaded server and followed the same basic 
pattern that Mongrel uses in its processing loop.  Everything works fine until 
you get a couple of clients hitting the server at the same time.  When that 
happens, I get:

/Library/Ruby/Site/1.8/thrift/transport/socket.rb:94:in `read': end of file 
reached (Thrift::TransportException)
        from /Library/Ruby/Site/1.8/thrift/transport.rb:103:in `read'
        from /Library/Ruby/Site/1.8/thrift/transport.rb:44:in `read_all'
        from /Library/Ruby/Site/1.8/thrift/protocol/binaryprotocol.rb:143:in 
`read_i32'
        from /Library/Ruby/Site/1.8/thrift/protocol/binaryprotocol.rb:80:in 
`read_message_begin'
        from /Library/Ruby/Site/1.8/thrift/client.rb:26:in `receive_message'
        from ./script/../lib/gen-rb/JobsService.rb:26:in `recv_search'
        from ./script/../lib/gen-rb/JobsService.rb:18:in `search'
        from script/jobs_client:22
        from script/jobs_client:17:in `times'
        from script/jobs_client:17

Then, I cooked up the example that is attached to this ticket.  I see two 
different behaviors based on where the transport.open/close calls are.  When 
the calls are inside the loop, all clients will hang once I start up 6-7 of 
them.  Once hung, none will ever move again (even new ones).  If I close all 
clients, then new clients execute normally again.

When the calls are outside the loop and the server is a SimpleServer, each new 
client will block until the previous client completes. Use the ThreadedServer, 
and things run fine. However, I don't think leaving the transport open will 
work in my environment.

Everything is done using the latest version of Thrift downloaded from the 
Apache site.

Here is my serve method from the Server class that I built for my purposes. I 
removed a lot of the cleanup and error handling so you can see the meat of it.

    # Listen on the port and process requests. This is very similar to the 
mongrel listen loop.
    # It returns the thread used so you can "join" it. You can also access the 
Server::acceptor
    # attribute to get the thread later. We do things this way so that we can 
have the main
    # thread watch and stop our listener gracefully.
    def serve()
      @acceptor = Thread.new do
        begin
          @server_transport.listen()
          loop do
            begin
              client = @server_transport.accept()
              transport = @transport_factory.get_transport(client)
              protocol = @protocol_factory.get_protocol(transport)
              thread = Thread.new(client, transport, protocol) do |c, t, p|
                  begin
                    handler = @handler_class.new()
                    processor = @processor_class.new(handler)
                    loop do
                      processor.process(p, p)
                    end
                  rescue Thrift::TransportException, Thrift::ProtocolException
                  ensure
                    t.close()
                  end
                end
                thread[:started_on] = Time.now
                @workers.add(thread)
              end
            end
          end
        ensure
          @server_transport.close()
        end
      end
      
      return @acceptor
    end

With this method I get the errors from the client above as soon as I fire up a 
second client.  The server remains healthy.

I notice that the new Thrift includes a Mongrel handler. I will investigate 
that now, but I would prefer to keep things as simple as possible.

Thanks in advance.

-Dave

> Expected blocking from TSocket but didn't get it
> ------------------------------------------------
>
>                 Key: THRIFT-171
>                 URL: https://issues.apache.org/jira/browse/THRIFT-171
>             Project: Thrift
>          Issue Type: Bug
>          Components: Library (Java), Library (Ruby)
>    Affects Versions: 0.1
>         Environment: CentOS 4.x
>            Reporter: Dave Dupre
>         Attachments: try.zip
>
>
> I have a Thrift server built in Ruby on Rails. It uses the TSimpleServer 
> class since my server is using Rails to generate HTML (Rails view code 
> expects to be single threaded).  I have two clients: one in Java and one in 
> Ruby.  Here is what I see:
> Ruby client:
> # Usual init code straight from the tutorial here
> transport.open
> 1000.times { client.my_method }
> transport.close
> The Java client is basically the same.  Unfortunately, I see two different 
> behaviors when running multiple client instances.  With a Ruby client, 
> execute client A, and it starts processing normally.  Execute client B while 
> client A is still running, and it blocks at transport.open until client A 
> completes.  This is what I expected.  However, if I do the same thing with 
> Java clients, both clients proceed in parallel.  Unfortunately, this gets the 
> server very confused and into a really bad state.  I'm using TSocket which 
> should be doing blocking I/O, but that is not what I'm seeing happen.
> Is there some magic that I can do to make this work?  Right now, I use 
> configuration to ensure that only one Java client thread/process is allowed 
> to talk to my Ruby server, but this is a total hack.  Switching to 
> TThreadedServer makes blocking go away, but I'm nervous about what that will 
> mean to the Rails controller and view code.  FYI, my server allows me to 
> generate HTML views via Thrift.  If it was a pure Ruby server, then I would 
> not be concerned, but since so much is dependent on code that usually assumes 
> to be single threaded, I'm concerned about introducing bugs.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to