Class: FastlaneCore::FastlanePty

Inherits:
Object
  • Object
show all
Defined in:
fastlane_core/lib/fastlane_core/fastlane_pty.rb

Class Method Summary collapse

Class Method Details

.process_statusObject

to ease mocking



75
76
77
# File 'fastlane_core/lib/fastlane_core/fastlane_pty.rb', line 75

def self.process_status
  $?
end

.spawn(command, &block) ⇒ Object



23
24
25
26
27
# File 'fastlane_core/lib/fastlane_core/fastlane_pty.rb', line 23

def self.spawn(command, &block)
  spawn_with_pty(command, &block)
rescue LoadError
  spawn_with_popen(command, &block)
end

.spawn_with_popen(command, &block) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'fastlane_core/lib/fastlane_core/fastlane_pty.rb', line 57

def self.spawn_with_popen(command, &block)
  status = nil
  require 'open3'
  Open3.popen2e(command) do |command_stdin, command_stdout, p| # note the inversion
    status = p.value
    yield(command_stdout, command_stdin, status.pid)
    command_stdin.close
    command_stdout.close
    raise StandardError, "Process crashed" if status.signaled?
    status.exitstatus
  end
rescue StandardError => e
  # Wrapping any error in FastlanePtyError to allow callers to see and use
  # $?.exitstatus that would usually get returned
  raise FastlanePtyError.new(e, status.exitstatus || e.exit_status, status)
end

.spawn_with_pty(command, &block) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'fastlane_core/lib/fastlane_core/fastlane_pty.rb', line 29

def self.spawn_with_pty(command, &block)
  require 'pty'
  PTY.spawn(command) do |command_stdout, command_stdin, pid|
    begin
      yield(command_stdout, command_stdin, pid)
    rescue Errno::EIO
      # Exception ignored intentionally.
      # https://stackoverflow.com/questions/10238298/ruby-on-linux-pty-goes-away-without-eof-raises-errnoeio
      # This is expected on some linux systems, that indicates that the subcommand finished
      # and we kept trying to read, ignore it
    ensure
      begin
        Process.wait(pid)
      rescue Errno::ECHILD, PTY::ChildExited
        # The process might have exited.
      end
    end
  end
  status = self.process_status
  raise StandardError, "Process crashed" if status.signaled?
  status.exitstatus
rescue StandardError => e
  # Wrapping any error in FastlanePtyError to allow callers to see and use
  # $?.exitstatus that would usually get returned
  status = self.process_status
  raise FastlanePtyError.new(e, status.exitstatus || e.exit_status, status)
end