def process(&block)
      !block_given? and log_and_raise(ParallelError, "You must supply a block to the process method!")

      config.ui.logger.debug { "forks(#{@forks.inspect})" }

      while (@forks.count >= config.max_forks) do
        wait
      end

      child_reader, parent_writer = IO.pipe
      parent_reader, child_writer = IO.pipe

      config.before_fork and config.before_fork.call(Process.pid)
      pid = Process.fork do
        begin
          TRAPPED_SIGNALS.each { |signal| Signal.trap(signal) { } }

          parent_writer.close
          parent_reader.close

          config.after_fork and config.after_fork.call(Process.pid)

          data = nil
          begin
            ::Timeout.timeout(config.child_timeout, ZTK::Parallel::Timeout) do
              data = block.call
            end
          rescue Exception => e
            config.ui.logger.fatal { e.message }
            e.backtrace.each do |line|
              config.ui.logger << "#{line}\n"
            end
            data = ExceptionWrapper.new(e)
          end

          if !data.nil?
            begin
              encoded_data = Base64.encode64(Zlib::Deflate.deflate(Marshal.dump(data)))
              config.ui.logger.debug { "write(#{encoded_data.length}B: #{data.inspect})" }
              child_writer.write(encoded_data)
            rescue Exception => e
              config.ui.logger.warn { "Exception while writing data to child_writer! - #{e.inspect}" }
            end
          end

        rescue Exception => e
          config.ui.logger.fatal { "Exception in Child Process Handler: #{e.inspect}" }

        ensure
          child_reader.close rescue nil
          child_writer.close rescue nil

          Process.exit!(0)
        end
      end
      config.after_fork and config.after_fork.call(Process.pid)

      child_reader.close
      child_writer.close

      fork = {:reader => parent_reader, :writer => parent_writer, :pid => pid}
      @forks << fork

      pid
    end
def process(&block)
      !block_given? and log_and_raise(ParallelError, "You must supply a block to the process method!")

      config.ui.logger.debug { "forks(#{@forks.inspect})" }

      while (@forks.count >= config.max_forks) do
        wait
      end

      child_reader, parent_writer = IO.pipe
      parent_reader, child_writer = IO.pipe

      config.before_fork and config.before_fork.call(Process.pid)
      pid = Process.fork do
        begin
          TRAPPED_SIGNALS.each { |signal| Signal.trap(signal) { } }

          parent_writer.close
          parent_reader.close

          config.after_fork and config.after_fork.call(Process.pid)

          data = nil
          begin
            ::Timeout.timeout(config.child_timeout, ZTK::Parallel::Timeout) do
              data = block.call
            end
          rescue Exception => e
            config.ui.logger.fatal { e.message }
            e.backtrace.each do |line|
              config.ui.logger << "#{line}\n"
            end
            data = ExceptionWrapper.new(e)
          end

          if !data.nil?
            begin
              encoded_data = Base64.encode64(Zlib::Deflate.deflate(Marshal.dump(data)))
              config.ui.logger.debug { "write(#{encoded_data.length}B: #{data.inspect})" }
              child_writer.write(encoded_data)
            rescue Exception => e
              config.ui.logger.warn { "Exception while writing data to child_writer! - #{e.inspect}" }
            end
          end

        rescue Exception => e
          config.ui.logger.fatal { "Exception in Child Process Handler: #{e.inspect}" }

        ensure
          child_reader.close rescue nil
          child_writer.close rescue nil

          Process.exit!(0)
        end
      end
      config.after_fork and config.after_fork.call(Process.pid)

      child_reader.close
      child_writer.close

      fork = {:reader => parent_reader, :writer => parent_writer, :pid => pid}
      @forks << fork

      pid
    end
@param [Hash] configuration Configuration options hash.
 @option config [Integer] :max_forks Maximum number of forks to use.
 @option config [Proc] :before_fork (nil) Proc to call before forking.
 @option config [Proc] :after_fork (nil) Proc to call after forking.
 Process in parallel.

 @yield Block should execute tasks to be performed in parallel.
 @yieldreturn [Object] Block can return any object to be marshalled back to
   the parent processes result set.
 @return [Integer] Returns the pid of the child process forked.