Class: ExecService::Controller

Inherits:
Object
  • Object
show all
Defined in:
lib/exec_service/controller.rb

Overview

An object that controls a subprocess. This object is returned from an execution running in the background, or is yielded to a control block for an execution running in the foreground. You can use this object to interact with the subcommand's streams, send signals to the process, and get its result.

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#errIO? (readonly)

The subcommand's standard error stream (which can be read from).

Returns:

  • (IO)

    if the command was configured with err: :controller

  • (nil)

    if the command was not configured with err: :controller



43
44
45
# File 'lib/exec_service/controller.rb', line 43

def err
  @err
end

#exceptionException? (readonly)

The exception raised when the process failed to start.

Exactly one of #exception and #pid will be non-nil.

Returns:

  • (Exception)

    if the process failed to start.

  • (nil)

    if the process start was successful.



63
64
65
# File 'lib/exec_service/controller.rb', line 63

def exception
  @exception
end

#inIO? (readonly)

The subcommand's standard input stream (which can be written to).

Returns:

  • (IO)

    if the command was configured with in: :controller

  • (nil)

    if the command was not configured with in: :controller



25
26
27
# File 'lib/exec_service/controller.rb', line 25

def in
  @in
end

#nameObject (readonly)

The subcommand's name.

Returns:

  • (Object)


16
17
18
# File 'lib/exec_service/controller.rb', line 16

def name
  @name
end

#outIO? (readonly)

The subcommand's standard output stream (which can be read from).

Returns:

  • (IO)

    if the command was configured with out: :controller

  • (nil)

    if the command was not configured with out: :controller



34
35
36
# File 'lib/exec_service/controller.rb', line 34

def out
  @out
end

#pidInteger? (readonly)

The process ID.

Exactly one of #exception and #pid will be non-nil.

Returns:

  • (Integer)

    if the process start was successful

  • (nil)

    if the process could not be started.



53
54
55
# File 'lib/exec_service/controller.rb', line 53

def pid
  @pid
end

Instance Method Details

#capture(which) ⇒ self?

Captures the remaining data in the given stream. After calling this, do not read directly from the stream.

Parameters:

  • which (:out, :err)

    Which stream to capture

Returns:

  • (self)

    if the stream was captured

  • (nil)

    if the stream was not captured because the process has completed or did not start successfully



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/exec_service/controller.rb', line 75

def capture(which)
  @streams_mutex.synchronize do
    return nil unless @streams_open
    stream = stream_for(which, allow_in: false)
    @join_threads << ::Thread.new do
      data = stream.read
      @captures_mutex.synchronize do
        @captures[which] = data
      end
    ensure
      stream.close
    end
  end
  self
end

#capture_errself

Captures the remaining data in the standard error stream. After calling this, do not read directly from the stream.

Returns:

  • (self)


107
108
109
# File 'lib/exec_service/controller.rb', line 107

def capture_err
  capture(:err)
end

#capture_outself

Captures the remaining data in the standard output stream. After calling this, do not read directly from the stream.

Returns:

  • (self)


97
98
99
# File 'lib/exec_service/controller.rb', line 97

def capture_out
  capture(:out)
end

#executing?boolean

Determine whether the subcommand is still executing

Returns:

  • (boolean)


243
244
245
# File 'lib/exec_service/controller.rb', line 243

def executing?
  @completion_thread&.status ? true : false
end

#kill(sig) ⇒ self Also known as: signal

Send the given signal to the process. The signal can be specified by name or number.

Parameters:

  • sig (Integer, String)

    The signal to send.

Returns:

  • (self)


232
233
234
235
# File 'lib/exec_service/controller.rb', line 232

def kill(sig)
  ::Process.kill(sig, pid) if pid
  self
end

#redirect(which, io, *io_args) ⇒ self?

Redirects the remainder of the given stream.

You can specify the stream as an IO or IO-like object, or as a file specified by its path. If specifying a file, you can optionally provide the mode and permissions for the call to File#open. You can also specify the value :null to indicate the null file.

If the stream is redirected to an IO-like object, it is not closed when the process is completed. (If it is redirected to a file specified by path, the file is closed on completion.)

After calling this, do not interact directly with the stream.

Parameters:

  • which (:in, :out, :err)

    Which stream to redirect

  • io (IO, StringIO, String, :null)

    Where to redirect the stream

  • io_args (Object...)

    The mode and permissions for opening the file, if redirecting to/from a file.

Returns:

  • (self)

    if the stream was redirected

  • (nil)

    if the stream was not redirected because the process has completed or did not start successfully



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/exec_service/controller.rb', line 134

def redirect(which, io, *io_args)
  @streams_mutex.synchronize do
    return nil unless @streams_open
    io = ::File::NULL if io == :null
    close_afterward = false
    if io.is_a?(::String)
      io_args = which == :in ? ["r"] : ["w"] if io_args.empty?
      io = ::File.open(io, *io_args)
      close_afterward = true
    end
    stream = stream_for(which, allow_in: true)
    @join_threads << ::Thread.new do
      if which == :in
        ::IO.copy_stream(io, stream)
      else
        ::IO.copy_stream(stream, io)
      end
    ensure
      stream.close
      io.close if close_afterward
    end
  end
  self
end

#redirect_err(io, *io_args) ⇒ self?

Redirects the remainder of the standard error stream.

You can specify the stream as an IO or IO-like object, or as a file specified by its path. If specifying a file, you can optionally provide the mode and permissions for the call to File#open. You can also specify the value :null to indicate the null file.

After calling this, do not interact directly with the stream.

Parameters:

  • io (IO, StringIO, String, :null)

    Where to redirect the stream

  • io_args (Object...)

    The mode and permissions for opening the file, if redirecting to a file.

Returns:

  • (self)

    if the stream was redirected

  • (nil)

    if the stream was not redirected because the process has completed or did not start successfully



221
222
223
# File 'lib/exec_service/controller.rb', line 221

def redirect_err(io, *io_args)
  redirect(:err, io, *io_args)
end

#redirect_in(io, *io_args) ⇒ self?

Redirects the remainder of the standard input stream.

You can specify the stream as an IO or IO-like object, or as a file specified by its path. If specifying a file, you can optionally provide the mode and permissions for the call to File#open. You can also specify the value :null to indicate the null file.

After calling this, do not interact directly with the stream.

Parameters:

  • io (IO, StringIO, String, :null)

    Where to redirect the stream

  • io_args (Object...)

    The mode and permissions for opening the file, if redirecting from a file.

Returns:

  • (self)

    if the stream was redirected

  • (nil)

    if the stream was not redirected because the process has completed or did not start successfully



177
178
179
# File 'lib/exec_service/controller.rb', line 177

def redirect_in(io, *io_args)
  redirect(:in, io, *io_args)
end

#redirect_out(io, *io_args) ⇒ self?

Redirects the remainder of the standard output stream.

You can specify the stream as an IO or IO-like object, or as a file specified by its path. If specifying a file, you can optionally provide the mode and permissions for the call to File#open. You can also specify the value :null to indicate the null file.

After calling this, do not interact directly with the stream.

Parameters:

  • io (IO, StringIO, String, :null)

    Where to redirect the stream

  • io_args (Object...)

    The mode and permissions for opening the file, if redirecting to a file.

Returns:

  • (self)

    if the stream was redirected

  • (nil)

    if the stream was not redirected because the process has completed or did not start successfully



199
200
201
# File 'lib/exec_service/controller.rb', line 199

def redirect_out(io, *io_args)
  redirect(:out, io, *io_args)
end

#result(timeout: nil) ⇒ ExecService::Result?

Wait for the subcommand to complete, and return a result object.

Parameters:

  • timeout (Numeric, nil) (defaults to: nil)

    The timeout in seconds, or nil to wait indefinitely.

Returns:



255
256
257
258
259
260
# File 'lib/exec_service/controller.rb', line 255

def result(timeout: nil)
  return nil if @completion_thread && !@completion_thread.join(timeout)
  # @completion_thread sets @result, so the final value is guaranteed
  # to be stable once the thread has joined above.
  @result
end