From: "Eregon (Benoit Daloze)" Date: 2021-08-19T16:42:06+00:00 Subject: [ruby-core:105013] [Ruby master Feature#18083] Capture error in ensure block. Issue #18083 has been updated by Eregon (Benoit Daloze). I think use-cases needing separate cleanups whether there is a Ruby exception or "normal execution or non-local control flow" will always be ugly, fundamentally because they do something hacky and approximative: the exception that happens inside is not a proof the resource is at fault, it could be anything, including a NoMemoryError or a SystemStackError for instance (which e.g. could be due to a bug in the block, not related to the resource at all). So in general, there should be one call to e.g. `close` in `ensure` and code should not attempt to differentiate (e.g., what happens for `File.open {}`). For the rare cases which do need to differentiate, I think `rescue Exception => error` + `if error` is fine. You literally want to test "any Ruby exception" or "any other exit from this block", and then `rescue Exception` just makes sense. It's true one should avoid `rescue Exception` in general, or at the very least make sure it's always re-raised to not swallow important and possibly unrelated errors. So RuboCop is right to warn for such usages as they should be avoided in general, and it's worth double-checking if one really needs to `rescue Exception`. But as every rule, there are exceptions, and this is a good exception to that rule, if you literally want to differentiate "any Ruby exception" or "any other exit from this block", then `rescue Exception` is *exactly* what one wants, just go ahead and suppress the RuboCop warning. ---------------------------------------- Feature #18083: Capture error in ensure block. https://bugs.ruby-lang.org/issues/18083#change-93416 * Author: ioquatix (Samuel Williams) * Status: Open * Priority: Normal ---------------------------------------- As discussed in https://bugs.ruby-lang.org/issues/15567 there are some tricky edge cases. As a general model, something like the following would be incredibly useful: ``` ruby begin ... ensure => error pp "error occurred" if error end ``` Currently you can get similar behaviour like this: ``` ruby begin ... rescue Exception => error raise ensure pp "error occurred" if error end ``` The limitation of this approach is it only works if you don't need any other `rescue` clause. Otherwise, it may not work as expected or require extra care. Also, Rubocop will complain about it. Using `$!` can be buggy if you call some method from `rescue` or `ensure` clause, since it would be set already. It was discussed extensively in https://bugs.ruby-lang.org/issues/15567 if you want more details. -- https://bugs.ruby-lang.org/ Unsubscribe: