lib/zk/client/threaded.rb in zk-1.5.1 vs lib/zk/client/threaded.rb in zk-1.5.2

- old
+ new

@@ -169,23 +169,24 @@ # this is the last status update we've received from the underlying connection @last_cnx_state = Zookeeper::ZOO_CLOSED_STATE @retry_duration = opts.fetch(:retry_duration, nil).to_i + yield self if block_given? + @fork_subs = [ ForkHook.prepare_for_fork(method(:pause_before_fork_in_parent)), ForkHook.after_fork_in_parent(method(:resume_after_fork_in_parent)), ForkHook.after_fork_in_child(method(:reopen)), ] ObjectSpace.define_finalizer(self, self.class.finalizer(@fork_subs)) - yield self if block_given? - connect if opts.fetch(:connect, true) end + # @private def self.finalizer(hooks) proc { hooks.each(&:unregister) } end # @option opts [Fixnum] :timeout how long we will wait for the connection @@ -257,22 +258,26 @@ logger.debug { "#{self.class}##{__method__}" } @cond.broadcast end - [@event_handler, @threadpool, @cnx].each(&:pause_before_fork_in_parent) + # the compact is here because the @cnx *may* be nil when this callback is fired by the + # ForkHook (in the case of ZK.open). The race is between the GC calling the finalizer + [@event_handler, @threadpool, @cnx].compact.each(&:pause_before_fork_in_parent) + ensure + logger.debug { "#{self.class}##{__method__} returning" } end # @private def resume_after_fork_in_parent @mutex.synchronize do raise InvalidStateError, "client must be paused? when you call #{__method__}" unless (@cli_state == CLI_PAUSED) @cli_state = CLI_RUNNING logger.debug { "#{self.class}##{__method__}" } - [@cnx, @event_handler, @threadpool].each(&:resume_after_fork_in_parent) + [@cnx, @event_handler, @threadpool].compact.each(&:resume_after_fork_in_parent) @cond.broadcast end end @@ -302,19 +307,21 @@ # if the user *doesn't* hate us, then we just join the shutdown_thread immediately # and wait for it to exit # shutdown_thread = Thread.new do @threadpool.shutdown(10) + + # this will call #close super @mutex.synchronize do logger.debug { "moving to :closed state" } @cli_state = CLI_CLOSED @cond.broadcast end end - on_tpool ? shutdown_thread : shutdown_thread.join + on_tpool ? shutdown_thread : shutdown_thread.join(30) end # {see Base#close} def close super