[Mongrel] mongrel thread safety and global variables

hemant gethemant at gmail.com
Fri Sep 1 08:48:04 EDT 2006


On 9/1/06, hemant <gethemant at gmail.com> wrote:
>
>
> In environment.rb file, I initialize a connection to some data vending
> servers, through TCP sockets.
>
> The connection object is global and hence the code:
>
> #environment.rb
> $generic_connection = ConnectionClass.instance (singleton class)
> $generic_connection.connect( this call will make the connection)
>
>
> The above approach is to make sure that, only one connection is made to
> the data vending servers.ConnectionClass is a library Class that, I have
> written to handle connections and to ensure exception handling and all that
> stuff.
>
> Now, in our rails code, whenever we need some data from these data vending
> servers, we use this global variable to get the data.
>
> #in controllers
> $generic_connection.get_data('<our internal protocol>')
>
>
>
> Since, we switched to mongrel, we are facing a strange issue. Our protocol
> code, specify what kind of data we want from data vending servers.So, lets
> say we want, x informatio, then we specify xxx as protocol code and get the
> data. protocol code "yyy" would give completely different kind of data.
> Now..sometimes what happens is, an Ajax call requests xxx protocol code and
> in the response we get data of protocol code yyy. Data vending servers are
> threaded again, and for each connection it starts a new thread and each
> request is served on a new thread.
> Data vending servers are again mostly written in ruby.
>
> Now, I am wondering where is the problem?
>
> As i know, mongrel serves requests on new threads, so what happens to this
> global variable that is shared among the threads.Is there a possiblity
> that, problem is here?
> I mean, lets say a thread is using this global variable for fetching data
> for protocol code xxx and same time another thread requests for protocol
> code yyy. My connection class, which is basically a proxy to these data
> vending servers, may not be thread safe.If this is the problem, then can
> anybody suggest better approach of making single connection to data vending
> servers, without using shared global variables.
>
>
>
> It could be a problem with our data vending servers also.But I am not so,
> sure about that.
>
>
For anyone interested here is the ConnectionClass code:

require 'socket'
require 'timeout'
require 'singleton'
require 'yaml'

class ConnectionClass
  include Singleton

  def connect
    p = YAML.load(File.read("#{RAILS_ROOT}/config/parameters.yaml"))
    @socket_file = p["socket_file"]
    return connect_to_proxy
  end


  def connect_to_proxy
    begin
      @proxy_con = UNIXSocket.open(@socket_file.strip)
      return @proxy_con
    rescue Exception => e
      return nil
    end
  end

  def get_data(request_string)
    req_array = request_string.split(':')
    code = req_array[0].strip
    msg = req_array[1].strip
    symbol = req_array[2].strip

    return get_data_from_proxy(code,symbol)

  end


  def get_data_from_proxy(code,symbol)
    temp_string = code + '<' + symbol + '>'

    ret_data = nil

    begin
      @proxy_con.puts(temp_string)
    rescue Errno::EPIPE
      unless connect_to_proxy.nil?
        @proxy_con.puts(temp_string)
      else
        return nil
      end
    rescue Exception => e
      return nil
    end

    begin
      timeout(8) do
        ret_data = @proxy_con.gets()
      end
    rescue Timeout::Error
      return nil
    rescue Exception => e
      return nil
    end


    if ret_data =~ /^600*/
      return nil
    elsif ret_data =~ /^620*/
      return nil
    else
      return ret_data
    end
  end

end

Evidently, when rails load(i.e mongrel starts), the only call made is,
$generic_connection.connect(from environment.rb), and hence within this
class, only @proxy_con should be shared among the threads IMHO.
So, what happens when subsequent calls to $generic_connection.get_data is
made from controller(ie mongrel threads)? while one thread is waiting for
@proxy_con.gets, another thread can call the same method, but the question
is, both the threads will share local variables defined within get_data and
get_data_from_proxy methods?

If i make, both the methods threaded, it should solve the problem? but i am
wondering, how mongrel would handle it.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://rubyforge.org/pipermail/mongrel-users/attachments/20060901/ae07b793/attachment-0001.html 


More information about the Mongrel-users mailing list