Parent

Files

Grit::Process

Override the Grit::Process class’s popen4 and waitpid methods to work around various quirks in JRuby.


Grit::Process includes logic for executing child processes and reading/writing from their standard input, output, and error streams.

Create an run a process to completion:

>> process = Grit::Process.new(['git', '--help'])

Retrieve stdout or stderr output:

>> process.out
=> "usage: git [--version] [--exec-path[=GIT_EXEC_PATH]]\n ..."
>> process.err
=> ""

Check process exit status information:

>> process.status
=> #<Process::Status: pid=80718,exited(0)>

Grit::Process is designed to take all input in a single string and provides all output as single strings. It is therefore not well suited to streaming large quantities of data in and out of commands.

Q: Why not use popen3 or hand-roll fork/exec code?

Constants

BUFSIZE

Maximum buffer size for reading

FakeStatus

JRuby always raises ECHILD on pids returned from its IO.popen4 method for some reason. Return a fake Process::Status object.

Attributes

err[R]

All data written to the child process’s stderr stream as a String.

out[R]

All data written to the child process’s stdout stream as a String.

runtime[R]

Total command execution time (wall-clock time)

status[R]

A Process::Status object with information on how the child exited.

Public Class Methods

new(argv, env={}, options={}) click to toggle source

Create and execute a new process.

argv - Array of [command, arg1, …] strings to use as the new

process's argv. When argv is a String, the shell is used
to interpret the command.

env - The new process’s environment variables. This is merged with

the current environment as if by ENV.merge(env).

options - Additional options:

  :input   => str to write str to the process's stdin.
  :timeout => int number of seconds before we given up.
  :max     => total number of output bytes
A subset of Process:spawn options are also supported on all
platforms:
  :chdir => str to start the process in different working dir.

Returns a new Process instance that has already executed to completion. The out, err, and status attributes are immediately available.

# File lib/grit/process.rb, line 58
def initialize(argv, env={}, options={})
  @argv = argv
  @env = env

  @options = options.dup
  @input = @options.delete(:input)
  @timeout = @options.delete(:timeout)
  @max = @options.delete(:max)
  @options.delete(:chdir) if @options[:chdir].nil?

  exec!
end

Public Instance Methods

popen4(*argv) click to toggle source

Use JRuby’s built in IO.popen4 but emulate the special spawn env and options arguments as best we can.

# File lib/grit/jruby.rb, line 9
def popen4(*argv)
  env = (argv.shift if argv[0].is_a?(Hash))  || {}
  opt = (argv.pop   if argv[-1].is_a?(Hash)) || {}

  # emulate :chdir option
  if opt[:chdir]
    previous_dir = Dir.pwd
    Dir.chdir(opt[:chdir])
  else
    previous_dir = nil
  end

  # emulate :env option
  if env.size > 0
    previous_env = ENV
    ENV.merge!(env)
  else
    previous_env = nil
  end

  pid, stdin, stdout, stderr = IO.popen4(*argv)
ensure
  ENV.replace(previous_env) if previous_env
  Dir.chdir(previous_dir)   if previous_dir
end
success?() click to toggle source

Determine if the process did exit with a zero exit status.

# File lib/grit/process.rb, line 84
def success?
  @status && @status.success?
end
waitpid(pid) click to toggle source
# File lib/grit/jruby.rb, line 38
def waitpid(pid)
  ::Process::waitpid(pid)
  $?
rescue Errno::ECHILD
  FakeStatus.new(pid, 0, true, true)
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.