Class: PTYBackgroundProcess

Inherits:
BackgroundProcess show all
Defined in:
lib/background_process/pty_background_process.rb

Instance Attribute Summary

Attributes inherited from BackgroundProcess

#pid, #stdin, #stdout

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from BackgroundProcess

#detect, #initialize, #interrupt, #kill, #running?

Constructor Details

This class inherits a constructor from BackgroundProcess

Class Method Details

.run(*command_with_args) ⇒ Object

Runs a subprocess in a pseudo terminal, tricking a program into not buffering its output.

A great write up on pseudo-terminals here: stackoverflow.com/questions/1154846/continuously-read-from-stdout-of-external-process-in-ruby

It has the following disadvantages:

  • You can't get the exit status

  • When the process dies, whatever output you haven't read yet is lost.

  • stderr is merged into stdout



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/background_process/pty_background_process.rb', line 14

def self.run(*command_with_args)
  command = sanitize_command(command_with_args)
  thread = Thread.new do # why run PTY separate thread? When a PTY instance
                         # dies, it raises PTY::ChildExited on the thread that
                         # spawned it, interrupting whatever happens to be
                         # running at the time
    PTY.spawn(command) do |output, input, pid|
      begin
        bp = new(pid, input, output)
        Thread.current[:background_process] = bp
        bp.wait
      rescue Exception => e
        puts e
        puts e.backtrace
      end
    end
  end
  sleep 0.01 until thread[:background_process]
  thread[:background_process]
end

Instance Method Details

#exitstatusObject

Raises:

  • (ArgumentError)


53
54
55
# File 'lib/background_process/pty_background_process.rb', line 53

def exitstatus
  raise ArgumentError, "exitstatus is not available for PTY subprocesses"
end

#stderrObject

Raises:

  • (ArgumentError)


35
36
37
# File 'lib/background_process/pty_background_process.rb', line 35

def stderr
  raise ArgumentError, "stderr is merged into stdout with PTY subprocesses"
end

#wait(timeout = nil) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/background_process/pty_background_process.rb', line 39

def wait(timeout = nil)
  begin
    Timeout.timeout(timeout) do
      Process.wait(@pid)
    end
  rescue Timeout::Error
    nil
  rescue PTY::ChildExited
    true
  rescue Errno::ECHILD
    true
  end
end