class ProcessExecuter::MonitoredPipe

Acts as a pipe that writes the data written to it to one or more destinations

{ProcessExecuter::MonitoredPipe} was created to expand the output redirection options for [Process.spawn](docs.ruby-lang.org/en/3.4/Process.html#method-c-spawn) and methods derived from it within the ‘ProcessExecuter` module.

This class’s initializer accepts any redirection destination supported by [Process.spawn](docs.ruby-lang.org/en/3.4/Process.html#method-c-spawn) (this is the ‘value` part of the file redirection option described in [the File Redirection section of `Process.spawn`](docs.ruby-lang.org/en/3.4/Process.html#module-Process-label-File+Redirection+-28File+Descriptor-29).

In addition to the standard redirection destinations, {ProcessExecuter::MonitoredPipe} also supports these additional types of destinations:

When a new MonitoredPipe is created, a pipe is created (via IO.pipe) and a thread is created to read data written to the pipe. As data is read from the pipe, it is written to the destination provided in the MonitoredPipe initializer.

If the destination raises an exception, the monitoring thread will exit, the pipe will be closed, and the exception will be saved in ‘#exception`.

> **⚠️ WARNING** > > ‘#close` must be called to ensure that (1) the pipe is closed, (2) all data is

read from the pipe and written to the destination, and (3) the monitoring thread is
killed.

@example Collect pipe data into a StringIO object

pipe_data = StringIO.new
begin
  pipe = ProcessExecuter::MonitoredPipe.new(pipe_data)
  pipe.write("Hello World")
ensure
  pipe.close
end
pipe_data.string #=> "Hello World"

@example Collect pipe data into a string AND a file

pipe_data_string = StringIO.new
pipe_data_file = File.open("pipe_data.txt", "w")
begin
  pipe = ProcessExecuter::MonitoredPipe.new([:tee, pipe_data_string, pipe_data_file])
  pipe.write("Hello World")
ensure
  pipe.close
end
pipe_data_string.string #=> "Hello World"
# It is your responsibility to close the file you opened
pipe_data_file.close
File.read("pipe_data.txt") #=> "Hello World"

@example Using a MonitoredPipe with Process.spawn

stdout_buffer = StringIO.new
begin
  stdout_pipe = ProcessExecuter::MonitoredPipe.new(stdout_buffer)
  pid = Process.spawn('echo Hello World', out: stdout_pipe)
  _waited_pid, status = Process.wait2(pid)
ensure
  stdout_pipe.close
end
stdout_buffer.string #=> "Hello World\n"

@api public