On Sat, 24 Jun 2006, Han H. 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.
if f.nil?
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