From: ara.t.howard@... Date: 2006-06-25T00:46:02+09:00 Subject: Re: Fork process with DRb client On Sat, 24 Jun 2006, Han Holl wrote: hi han- > The problem with this approach is that you have to know the uri of the > server at fork time, which can be a problem. it shouldn't be, you can do, for example uri = drbobject.__drburi eg. if you have a drb object you always have it's uri. if you have it's uri you can always detach and re-attach. though i agree it's not that elegant. > (And I didn't realize that you can destroy a DRbObject with > DRb.stop_service -- I associate that with the server side of things). yeah, it seems like it. remember though, every ruby program which uses drb is a servant - drb is always both server and client. fyi. > I've found a mote generic way of forking a process that is a DRb client, but > this has as drawback that it has an initimate knowlegde of the way DRb is > implemented. > > module DRb > class DRbConn > def self.fork > f = @mutex.synchronize do > Process::fork > end > if f.nil? > @pool = [] > if block_given? > yield > exit 0 > end > end > f > end > end > end > > This just deletes the commection pool in the child. Forking within the > mutex is because it's possible to fork with some other thread having the > mutex locked, which causes problems for the one-thread child. doesn't it leave open file handles lying around? > But it's a bit of a kludge and I would prefer it if DRbObject had a method > to deal with it. agreed. it's always tough to carry open file handles across a fork - sometimes is just seems easier to code around it. for instance, by setting up a ring server where each service registers in the parent. then all children simply grab drbobjects of of that ring server. maybe something like this might apply to your problem: harp:~ > ruby a.rb [[:key, :val]] [:val] harp:~ > cat a.rb require 'drb' require 'rinda/ring' require 'rinda/tuplespace' require 'tmpdir' require 'yaml' STDOUT.sync = STDERR.sync = true def start_ring_server Rinda::RingServer.new Rinda::TupleSpace.new end def find_ring_server Rinda::TupleSpaceProxy.new Rinda::RingFinger::new.lookup_ring_any end def drb_join begin; DRb.thread.join; rescue Exception; exit; end end children = [] # # one process starts a ring server. this could also be the parent. other # processes, or even the parent, can register drb objects with this ring # server. # children << fork{ DRb.start_service rs = start_ring_server drb_join } # # this one starts up a hash server and registers it's location # children << fork{ (dhash = {}).extend DRbUndumped DRb.start_service nil, dhash rs = find_ring_server rs.write [:dhash, dhash] drb_join } # # this one starts up an array server and registers it's location # children << fork{ (darray = []).extend DRbUndumped DRb.start_service nil, darray rs = find_ring_server rs.write [:darray, darray] drb_join } # # now any child, or the parent, can find and use these drb objects without # knowing their locations or requiring a connection before forking - only # the 'name' of the object need be known. # Process.waitpid fork{ DRb.start_service rs = find_ring_server tuple = rs.read [:dhash, nil] dhash = tuple.last dhash[:key] = :val tuple = rs.read [:darray, nil] darray = tuple.last darray << :val } # # here the parent finds the dhash and darray to print them out # DRb.start_service rs = find_ring_server tuple = rs.read [:dhash, nil] dhash = tuple.last tuple = rs.read [:darray, nil] darray = tuple.last p dhash.map #=> [[:key, :val]] p darray.map #=> [:val] # # wait for children # at_exit{ children.each{|cid| Process.kill 'TERM', cid rescue next} loop{ Process.wait Process::WNOHANG rescue break } } STDIN.gets regards. -a -- suffering increases your inner strength. also, the wishing for suffering makes the suffering disappear. - h.h. the 14th dali lama