Module: Hydra::Derivatives::Processors::ShellBasedProcessor::ClassMethods

Defined in:
lib/hydra/derivatives/processors/shell_based_processor.rb

Instance Method Summary collapse

Instance Method Details

#all_eof?(files) ⇒ Boolean

Returns:

  • (Boolean)


104
105
106
# File 'lib/hydra/derivatives/processors/shell_based_processor.rb', line 104

def all_eof?(files)
  files.find { |f| !f.eof }.nil?
end

#execute(command) ⇒ Object



43
44
45
46
47
48
49
50
# File 'lib/hydra/derivatives/processors/shell_based_processor.rb', line 43

def execute(command)
  context = {}
  if timeout
    execute_with_timeout(timeout, command, context)
  else
    execute_without_timeout(command, context)
  end
end

#execute_with_timeout(timeout, command, context) ⇒ Object



52
53
54
55
56
57
58
59
60
# File 'lib/hydra/derivatives/processors/shell_based_processor.rb', line 52

def execute_with_timeout(timeout, command, context)
  Timeout.timeout(timeout) do
    execute_without_timeout(command, context)
  end
rescue Timeout::Error
  pid = context[:pid]
  Process.kill("KILL", pid)
  raise Hydra::Derivatives::TimeoutError, "Unable to execute command \"#{command}\"\nThe command took longer than #{timeout} seconds to execute"
end

#execute_without_timeout(command, context) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/hydra/derivatives/processors/shell_based_processor.rb', line 62

def execute_without_timeout(command, context)
  error_buffer = ''
  stdin, stdout, stderr, wait_thr = popen3(command)
  context[:pid] = wait_thr[:pid]
  files = [stderr, stdout]
  stdin.close

  until all_eof?(files)
    ready = IO.select(files, nil, nil, 60)

    next unless ready
    readable = ready[0]
    readable.each do |f|
      fileno = f.fileno

      begin
        data = f.read_nonblock(BLOCK_SIZE)

        case fileno
        when stderr.fileno
          updated_error_buffer = error_buffer.dup
          updated_error_buffer << data
          error_buffer = updated_error_buffer
        end
      rescue IO::WaitReadable
        Hydra::Derivatives::Logger.warn "Caught an IO::WaitReadable error in ShellBasedProcessor. Retrying..."
        IO.select([f], nil, nil, 60)
        retry
      rescue EOFError
        Hydra::Derivatives::Logger.debug "Caught an eof error in ShellBasedProcessor"
        # No big deal.
      end
    end
  end

  stdout.close
  stderr.close
  exit_status = wait_thr.value

  raise "Unable to execute command \"#{command}\". Exit code: #{exit_status}\nError message: #{error_buffer}" unless exit_status.success?
end