Project

General

Profile

Actions

Bug #18375

closed

Timeout.timeout(sec, klass: MyExceptionClass) can not retry correctly.

Added by zw963 (Wei Zheng) 8 months ago. Updated 8 months ago.

Status:
Rejected
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:106358]

Description

Following is a example for describe this issue.

class DelayError < Exception
end

Timeout.timeout(2, DelayError) do |arg|
  puts 'start'
  sleep 10
rescue DelayError
  puts '*'*10
  retry
end

Will output

start
**********
start

What i expected is:

start
**********
start
**********
start
**********
...

Basically, what i expected equivalent is:

begin
  Timeout.timeout(2) do |arg|
    puts 'start'
    sleep 10
  end
rescue TimeoutError
  puts '*'*10
  retry
end
Actions #1

Updated by zw963 (Wei Zheng) 8 months ago

  • Description updated (diff)

Updated by jeremyevans0 (Jeremy Evans) 8 months ago

  • Status changed from Open to Rejected

I don't think this is a bug, and I don't think timeout can work with your proposed code. There's no way the block-level rescue can work the way you want, since what you want requires the timeout method be called again.

This code:

Timeout.timeout(2, DelayError) do |arg|
  puts 'start'
  sleep 10
rescue DelayError
  puts '*'*10
  retry
end

is short for:

Timeout.timeout(2, DelayError) do |arg|
  begin
    puts 'start'
    sleep 10
  rescue DelayError
    puts '*'*10
    retry
  end
end

It's not short for:

begin
  Timeout.timeout(2, DelayError) do |arg|
    puts 'start'
    sleep 10
  end
rescue DelayError
  puts '*'*10
  retry
end

Even if it were short for that, that code doesn't work the way you want either (looks like an infinite loop). You probably want something like:

deadline = Time.now + 10
begin
  Timeout.timeout(2, DelayError) do |arg|
    puts 'start'
    sleep(deadline - Time.now)
  end
rescue DelayError
  puts '*'*10
  retry
end

Updated by zw963 (Wei Zheng) 8 months ago

jeremyevans0 (Jeremy Evans) wrote in #note-2:

I don't think this is a bug, and I don't think timeout can work with your proposed code. There's no way the block-level rescue can work the way you want, since what you want requires the timeout method be called again.

This code:

Timeout.timeout(2, DelayError) do |arg|
  puts 'start'
  sleep 10
rescue DelayError
  puts '*'*10
  retry
end

is short for:

Timeout.timeout(2, DelayError) do |arg|
  begin
    puts 'start'
    sleep 10
  rescue DelayError
    puts '*'*10
    retry
  end
end

It's not short for:

begin
  Timeout.timeout(2, DelayError) do |arg|
    puts 'start'
    sleep 10
  end
rescue DelayError
  puts '*'*10
  retry
end

Even if it were short for that, that code doesn't work the way you want either (looks like an infinite loop). You probably want something like:

deadline = Time.now + 10
begin
  Timeout.timeout(2, DelayError) do |arg|
    puts 'start'
    sleep(deadline - Time.now)
  end
rescue DelayError
  puts '*'*10
  retry
end

In fact, if consider following code more useful than the actually form.

begin
  Timeout.timeout(2, DelayError) do |arg|
    puts 'start'
    sleep 10
  end
rescue DelayError
  puts '*'*10
  retry
end

Perhaps, we should do some specially process for Timeout.timeout rescue block.

Actions

Also available in: Atom PDF