Robert Klemme wrote:
> codeslinger wrote:
> > 1. Is there a commensurate to Java's setDaemon() functionality for
> > Ruby? I've looked around on the Web, but I can't find reference to
> > anything and there's nothing in the docs about it. For those not
> > familiar with Java, setDaemon() is equivalent to setting a thread to a
> > "detached" state in pthread lingo.
>
> No.  You will have to terminate them manually on exit.

If this is true (see my last post), then this is a design flaw in
Ruby's threading library. This particular application will be
long-running and cannot afford to have dead threads laying around
waiting for exit (which hopefully will never come). I understand that I
can join the threads in the main loop periodically to avoid this fate,
but that is still hackish. Perhaps a Thread#join_on_exit= or
Thread#autojoin= or Thread#detach= method would fit the bill for this?

> > class X
> >   def initialize
> >     srv = TCPServer.new nil, 8008
> >     Thread.abort_on_exception = true
> >     Thread.start srv, &ServerMain
> >     while true
> >         # doing main thread stuff in here
>
> Don't do that.  Simply fork off a thread that does the connection handling
> and return.  Initializers are for initialization but should not contain
> the processing.

The above code was just an example. That's not what the real code does
(its a port of some Java code), but since it is overwhelmingly large, I
wanted to show just the crux of the problem without all the other code
clouding the issue. My example wasn't the best Ruby, as you've pointed
out ;-)

> > Since ServerMain and ConnectionMain are lambdas, I would have expected
> > them to be able to locate the handle_sock_data() method. Why can't
> > they, and is there some way for me to get them to be able to see said
> > method?
>
> Your lambdas are class level constants but the method is an instance
> method.  You rather want one lambda instance per onstance of X.  But
> blocks will do the job as well.  Did you check the example for TCPServer?
> It's below this:
> http://www.ruby-doc.org/docs/ProgrammingRuby/html/lib_network.html#SOCKSSocket.close
>
> require 'socket'
>
> class X
>   attr_reader :thread
>
>   def initialize
>     @thread = Thread.new( TCPServer.new( nil, 8008 ) ) do |server|
>       while ( sess = server.accept )
>         Thread.new(sess) do |session|
>            handle_data sess.gets
>         end
>       end
>     end
>   end

Yeah, I am doing something similar in the real code (see below), but I
have to hunt around for a port to listen on, so the exact code above
wouldn't work for me. Plus, as I've said, the code inside the lambdas
is kind of large, and would cloud readability if I put it in the middle
of the initialize function. The real code reads:

<snip>
    def initialize datadir, namenodeaddr
            [...]
            thread_main_init
            ss = nil
            tmpport = 50010
            machinename = DataNode.get_local_ip namenodeaddr[0]
            until ss
                begin
                    ss = TCPServer.new machinename, tmpport
                    LOG.info "Opened server at #{tmpport}"
                rescue IOError => e
                    LOG.info "Could not open server at #{tmpport},
trying new port"
                    tmpport += 1
                end
            end
            @localname = "#{machinename}:#{tmpport}"
            @dataxceive_srv = Thread.start ss, &@data_xceive_server
            [...]
        end
</snip>

The @data_xceive_server is one of the lambda's that I am creating in
the thread_main_init() method (the others are for client connection
handling).

> Take care to synchronize access to shared resources in connection
> handling.

I got that. Thanks for all the help, Robert.

--
Toby DiPasquale