module Fluent::DetachProcessImpl

def detach_process_impl(num, &block)

def detach_process_impl(num, &block)
  children = []
  num.times do |i|
    pid, forward_thread = DetachProcessManager.instance.fork(self)
    if pid
      # parent process
      $log.info "detached process", :class=>self.class, :pid=>pid
      children << [pid, forward_thread]
      next
    end
    # child process
    begin
      on_detach_process(i)
      block.call
      # disable Engine.stop called by signal handler
      Engine.define_singleton_method(:stop) do
        # do nothing
      end
      # override signal handlers called by parent process
      fin = FinishWait.new
      trap :INT do
        fin.stop
      end
      trap :TERM do
        fin.stop
      end
      #forward_thread.join  # TODO this thread won't stop because parent doesn't close pipe
      fin.wait
      exit! 0
    ensure
      $log.error "unknown error while shutting down this child process", :error=>$!.to_s, :pid=>Process.pid
      $log.error_backtrace
    end
    exit! 1
  end
  # parent process
  # override shutdown method to kill child processes
  define_singleton_method(:shutdown) do
    children.each {|pair|
      begin
        pid = pair[0]
        forward_thread = pair[1]
        if pid
          Process.kill(:TERM, pid)
          forward_thread.join   # wait until child closes pipe
          Process.waitpid(pid)
          pair[0] = nil
        end
      rescue
        $log.error "unknown error while shutting down remote child process", :error=>$!.to_s
        $log.error_backtrace
      end
    }
  end
  # override target.emit and write event stream to the pipe
  forwarders = children.map {|pair| pair[1].forwarder }
  if forwarders.length > 1
    # use roundrobin
    fwd = DetachProcessManager::MultiForwarder.new(forwarders)
  else
    fwd = forwarders[0]
  end
  define_singleton_method(:emit) do |tag,es,chain|
    chain.next
    fwd.emit(tag, es)
  end
end

def on_detach_process(i)

def on_detach_process(i)
end