Search code examples
rubymultithreadingsoap4r

Thread lockup in ruby with Soap4r


This is related to a question I asked here: Thread Locking in Ruby (use of soap4r and QT)

However it is particular to one part of that question and is supported by a simpler example. The test code is:

require 'rubygems'
require 'thread'
require 'soap/rpc/standaloneserver'

class SOAPServer < SOAP::RPC::StandaloneServer

    def initialize(* args)
        super
        # Exposed methods
        add_method(self, 'test', 'x', 'y')
    end

    def test(x, y)
        return x + y
    end
end


myServer = SOAPServer.new('monitorservice', 'urn:ruby:MonitorService', 'localhost',         4004)

Thread.new do
    puts 'Starting web services'
    myServer.start
    puts 'Ending web services'
end

sleep(4)

#Thread.new do
    testnum = 0
    while testnum < 4000 do
        testnum += 1
        puts myServer.test(0,testnum)
        sleep(2)
    end
#end

puts myServer.test(0,4001)
puts myServer.test(0,4002)
puts myServer.test(0,4003)
puts myServer.test(0,4004)
gets

When I run this with the thread commented out everything runs along fine. However, once the thread is put in the process hangs. I poked into Webrick and found that the stop occurs here (the puts are, of course, mine):

while @status == :Running
      begin
        puts "1.1"
        if svrs = IO.select(@listeners, nil, nil, 2.0)
          svrs[0].each{|svr|
        puts "-+-"
            @tokens.pop          # blocks while no token is there.
            if sock = accept_client(svr)
              th = start_thread(sock, &block)
              th[:WEBrickThread] = true
              thgroup.add(th)
            else
              @tokens.push(nil)
            end
          }
        end
        puts ".+."

When run with the thread NOT commented out I get something like this: Starting web services

1.1
.+.
1.1
4001
4002
4003
4004
1
.+.
1.1

Solution

  • The trailing gets blocks Ruby's IO. I'm not sure why. If it is replaced with pretty much anything the program works. I used a sleeping loop:

    loop do
        sleep 1
    end
    

    ADDED: I should note that I also get strange behavior with sleep based on the sleep increment. In the end I abandoned Ruby since the threading behavior was too wonky.