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



79
80
81
# File 'fastlane_core/lib/fastlane_core/fastlane_pty.rb', line 79

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



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'fastlane_core/lib/fastlane_core/fastlane_pty.rb', line 61

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(original_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
56
57
58
59
# File 'fastlane_core/lib/fastlane_core/fastlane_pty.rb', line 29

def self.spawn_with_pty(original_command, &block)
  require 'pty'
  # this forces the PTY flush - fixes #21792
  command = ENV['FASTLANE_EXEC_FLUSH_PTY_WORKAROUND'] ? "#{original_command};" : original_command
  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
      command_stdin.close
      command_stdout.close
      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