Class: Command::Runner::Backends::Spawn

Inherits:
Fake
  • Object
show all
Defined in:
lib/command/runner/backends/spawn.rb

Overview

Spawns a process using ruby's Process.spawn.

Direct Known Subclasses

PosixSpawn

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Fake

#ran?, unsafe?, #unsafe?, unsafe_execution?

Constructor Details

#initializeSpawn

Initialize the backend.


19
20
21
# File 'lib/command/runner/backends/spawn.rb', line 19

def initialize
  super
end

Class Method Details

.available?(_ = false) ⇒ Boolean

Returns whether or not this backend is available on this platform. Process.spawn doesn't work the way we want it to on JRuby 1.9 mode, so we prevent this from being used on that platform.


14
15
16
# File 'lib/command/runner/backends/spawn.rb', line 14

def self.available?(_ = false)
  Process.respond_to?(:spawn) && !(RUBY_PLATFORM == "java" && RUBY_VERSION =~ /\A1\.9/)
end

Instance Method Details

#call(command, arguments, env = {}, options = {}) {|Message| ... } ⇒ Message, Object

Note:

The block is called in another thread, so in ruby versions other than MRI, make sure your code is thread-safe.

Run the given command and arguments, in the given environment.

Yields:

  • (Message)

    when the command finishes.

Raises:

  • (Errno::ENOENT)

    if the command doesn't exist.


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/command/runner/backends/spawn.rb', line 32

def call(command, arguments, env = {}, options = {}, &block)
  super
  stderr_r, stderr_w = IO.pipe
  stdout_r, stdout_w = IO.pipe
  stdin_r,  stdin_w  = IO.pipe
  clean_exceptions   = options.delete(:clean_exceptions) || false

  if options[:input]
    stdin_w.write(options.delete(:input))
  end
  new_options = options.merge(:in => stdin_r,
    :out => stdout_w, :err => stderr_w)

  stdin_w.close

  line = [command, *arguments].join(' ')

  start_time = Time.now
  process_id = spawn(env, command, arguments, new_options)

  future do
    _, status = wait2(process_id)
    end_time = Time.now

    [stdout_w, stderr_w].each(&:close)

    message = Message.new :process_id => process_id,
                :exit_code  => status.exitstatus,
                :finished   => true,
                :time       => (start_time - end_time).abs,
                :env        => env,
                :options    => options,
                :stdout     => stdout_r.read,
                :stderr     => stderr_r.read,
                :line       => line,
                :executed   => true,
                :status     => status

    if block_given?
      block.call(message)
    else
      message
    end
  end
end

#spawn(env, command, arguments, options) ⇒ Numeric

Spawn the given process, in the environment with the given options.

See Also:

  • Process.spawn

83
84
85
86
87
88
89
# File 'lib/command/runner/backends/spawn.rb', line 83

def spawn(env, command, arguments, options)
  if options.delete(:unsafe)
    Process.spawn(env, "#{command} #{arguments.join(' ')}", options)
  else
    Process.spawn(env, command, *arguments, options)
  end
end

#wait2(process_id = -1)) ⇒ Array<(Numeric, Process::Status)>

Waits for the given process, and returns the process id and the status.

See Also:

  • Process.wait2

96
97
98
# File 'lib/command/runner/backends/spawn.rb', line 96

def wait2(process_id = -1)
  Process.wait2(process_id)
end