Class: Roast::Helpers::TimeoutHandler
- Inherits:
-
Object
- Object
- Roast::Helpers::TimeoutHandler
- Defined in:
- lib/roast/helpers/timeout_handler.rb
Overview
Shared timeout handling logic for command-based tools
This class provides centralized timeout functionality for executing shell commands with proper process management and resource cleanup.
Constant Summary collapse
- DEFAULT_TIMEOUT =
30- MAX_TIMEOUT =
300
Class Method Summary collapse
-
.call(command, timeout: DEFAULT_TIMEOUT, working_directory: Dir.pwd) ⇒ Array<String, Integer>
Execute a command with timeout using Open3 with proper process cleanup.
-
.validate_timeout(timeout) ⇒ Integer
Validate and normalize timeout value.
Class Method Details
.call(command, timeout: DEFAULT_TIMEOUT, working_directory: Dir.pwd) ⇒ Array<String, Integer>
Execute a command with timeout using Open3 with proper process cleanup
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/roast/helpers/timeout_handler.rb', line 29 def call(command, timeout: DEFAULT_TIMEOUT, working_directory: Dir.pwd) timeout = validate_timeout(timeout) output = "" exit_status = nil wait_thr = nil begin Timeout.timeout(timeout) do stdin, stdout, stderr, wait_thr = Open3.popen3(command, chdir: working_directory) stdin.close # Prevent hanging on stdin-waiting commands output = stdout.read + stderr.read wait_thr.join exit_status = wait_thr.value.exitstatus [stdout, stderr].each(&:close) end rescue Timeout::Error # Clean up any remaining processes to prevent zombies cleanup_process(wait_thr) if wait_thr&.alive? raise Timeout::Error, "Command '#{command}' in '#{working_directory}' timed out after #{timeout} seconds" end [output, exit_status] end |
.validate_timeout(timeout) ⇒ Integer
Validate and normalize timeout value
57 58 59 60 61 |
# File 'lib/roast/helpers/timeout_handler.rb', line 57 def validate_timeout(timeout) return DEFAULT_TIMEOUT if timeout.nil? || timeout <= 0 [timeout, MAX_TIMEOUT].min end |