From: "zw963 (Wei Zheng)" Date: 2021-12-03T15:44:12+00:00 Subject: [ruby-core:106471] [Ruby master Bug#18375] Timeout.timeout(sec, klass: MyExceptionClass) can not retry correctly. Issue #18375 has been updated by zw963 (Wei Zheng). 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: > > ```ruby > Timeout.timeout(2, DelayError) do |arg| > puts 'start' > sleep 10 > rescue DelayError > puts '*'*10 > retry > end > ``` > > is short for: > > ```ruby > Timeout.timeout(2, DelayError) do |arg| > begin > puts 'start' > sleep 10 > rescue DelayError > puts '*'*10 > retry > end > end > ``` > > It's not short for: > > ```ruby > 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: > > ```ruby > deadline = Time.now + 10 > begin > Timeout.timeout(2, DelayError) do |arg| > puts 'start' > sleep(deadline - Time.now) > end > rescue DelayError > puts '*'*10 > retry > end 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: > > ```ruby > Timeout.timeout(2, DelayError) do |arg| > puts 'start' > sleep 10 > rescue DelayError > puts '*'*10 > retry > end > ``` > > is short for: > > ```ruby > Timeout.timeout(2, DelayError) do |arg| > begin > puts 'start' > sleep 10 > rescue DelayError > puts '*'*10 > retry > end > end > ``` > > It's not short for: > > ```ruby > 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: > > ```ruby > deadline = Time.now + 10 > begin > Timeout.timeout(2, DelayError) do |arg| > puts 'start' > sleep(deadline - Time.now) > end > rescue DelayError > puts '*'*10 > retry > end > ``` 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: > > ```ruby > Timeout.timeout(2, DelayError) do |arg| > puts 'start' > sleep 10 > rescue DelayError > puts '*'*10 > retry > end > ``` > > is short for: > > ```ruby > Timeout.timeout(2, DelayError) do |arg| > begin > puts 'start' > sleep 10 > rescue DelayError > puts '*'*10 > retry > end > end > ``` > > It's not short for: > > ```ruby > 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: > > ```ruby > 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. ```rb 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. ---------------------------------------- Bug #18375: Timeout.timeout(sec, klass: MyExceptionClass) can not retry correctly. https://bugs.ruby-lang.org/issues/18375#change-95128 * Author: zw963 (Wei Zheng) * Status: Rejected * Priority: Normal * ruby -v: 3.0.3 * Backport: 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN ---------------------------------------- Following is a example for describe this issue. ```rb 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: ```rb begin Timeout.timeout(2) do |arg| puts 'start' sleep 10 end rescue TimeoutError puts '*'*10 retry end ``` -- https://bugs.ruby-lang.org/ Unsubscribe: