Module: RubyTimeoutSafe

Defined in:
lib/ruby_timeout_safe.rb,
lib/ruby_timeout_safe/version.rb,
sig/ruby_timeout_safe.rbs

Overview

The RubyTimeoutSafe module provides a safe and reliable timeout functionality for executing Ruby blocks. It uses POSIX threads (pthreads) and signal handling to ensure that timeouts are enforced even in the presence of blocking operations or long-running computations.

Constant Summary collapse

VERSION =

The current version of the Ruby::Timeout::Safe module.

Returns:

  • (String)
'1.0.1'

Class Method Summary collapse

Class Method Details

.timeout(seconds = nil) { ... } ⇒ Object

Executes the given block with a specified timeout duration.

Parameters:

  • seconds (Integer, Float, nil) (defaults to: nil) —

    The timeout duration in seconds. If nil is provided, the block will be executed without a timeout.

  • seconds: (Integer)

Yields:

  • The block to be executed with the specified timeout.

Yield Returns:

  • (Object)

Returns:

  • (Object) —

    The result of the block execution.

Raises:

  • (ArgumentError) —

    If the seconds argument is negative.

  • (Timeout::Error) —

    If the block execution exceeds the specified timeout.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'sig/ruby_timeout_safe.rbs', line 17

def self.timeout(seconds = nil)
  return yield if seconds.nil? || seconds.zero?

  raise ArgumentError, 'timeout value must be at least 0.1 second' if seconds < 0.1

  current_thread = Thread.current

  start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  s_thread = Thread.new do
    loop do
      elapsed_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time
      break if elapsed_time >= seconds

      sleep(0.05) # Sleep briefly to prevent busy-waiting
    end
    current_thread.raise Timeout::Error, 'execution expired'
  end

  yield
ensure
  s_thread.kill if s_thread&.alive?
end