# this is a race condition from - http://github.com/defunkt/cijoe/
#
    status = Open4.popen4(runner_command) do |pid, stdin, stdout, stderr|
      build.pid = pid
      write_build 'current', build
      err, out = stderr.read.strip, stdout.read.strip # < child process blocks when this becomes full
                 # ^
                 # ^
                 # ^
                 # ^ we read stderr first, synchronously, while stdout is
                 # ^ filling up with PIPE_MAX - causing the producing child
                 # ^ process to hang - now our call to reading stderr will
                 # ^ never return since the child is won't send EOF until it can
                 # ^ finish sending stdout - which it is blocked on
    end

# there is no way to read stdout/stderr of a child process, in ruby or any
# other language,  without risking a child process hang unless you
#
# 1) use select on *all of* stdout/stderr/stdin
#
# 2) use threads to write/read all three at once
#
# open4 implements #2 for you as Open4.spawn see
# http://github.com/ahoward/open4/blob/master/samples/spawn.rb


# for the above usage it'd be much simpler to use systemu - which cannot
# process streams in realtime, but saves the user from having to consider the
# intricacies of dealing with 3 streams.  it also works on any platform,
# including windows.  the above code could be written safely and simply using
# systemu as
#
  status, stdout, stderr =
    systemu(runner_command) do |pid|
      build.pid = pid
      write_build('current', build)
    end