Module: Msf::Exploit::Retry

Instance Method Summary collapse

Instance Method Details

#poll_until_truthy(timeout:, interval: 1) ⇒ Object

Poll the block at a fixed interval until it returns a truthy value or the timeout expires. Unlike retry_until_truthy, this uses a consistent delay between attempts rather than exponential backoff — useful when checking for a state change that could happen at any moment (e.g. waiting for a session).

Parameters:

  • timeout (Integer)

    maximum seconds to wait

  • interval (Numeric) (defaults to: 1)

    seconds between each poll (default: 1)

Returns:

  • the truthy value of the block, or nil if timed out



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/msf/core/exploit/retry.rb', line 42

def poll_until_truthy(timeout:, interval: 1)
  start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
  ending_time = start_time + timeout

  loop do
    result = yield
    return result if result

    remaining = ending_time - Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
    break if remaining <= 0

    sleep [interval, remaining].min
  end

  nil
end

#retry_until_truthy(timeout:) ⇒ Object

Retry the block until it returns a truthy value. Each iteration attempt will be performed with an exponential backoff. If the timeout period surpasses, nil is returned.

Parameters:

  • Integer

    timeout the number of seconds to wait before the operation times out

Returns:

  • the truthy value of the block is returned or nil if it timed out



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/msf/core/exploit/retry.rb', line 8

def retry_until_truthy(timeout:)
  start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
  ending_time = start_time + timeout
  retry_count = 0
  while Process.clock_gettime(Process::CLOCK_MONOTONIC, :second) < ending_time
    result = yield
    return result if result

    retry_count += 1
    remaining_time_budget = ending_time - Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
    break if remaining_time_budget <= 0

    delay = 2**retry_count
    if delay >= remaining_time_budget
      delay = remaining_time_budget
      vprint_status("Final attempt. Sleeping for the remaining #{delay} seconds out of total timeout #{timeout}")
    else
      vprint_status("Sleeping for #{delay} seconds before attempting again")
    end

    sleep delay
  end

  nil
end