[#104740] [Ruby master Feature#18057] Introduce Array#average — ggmichaelgo@...

Issue #18057 has been reported by ggmichaelgo (Michael Go).

14 messages 2021/08/02

[#104774] [Ruby master Bug#18061] Execshield test: libruby.so.N.N.N: FAIL: property-note test because no .note.gnu.property section found — jaruga@...

Issue #18061 has been reported by jaruga (Jun Aruga).

48 messages 2021/08/04

[#104780] [Ruby master Bug#18062] Ruby with enabled LTO segfaults during build — v.ondruch@...

Issue #18062 has been reported by vo.x (Vit Ondruch).

30 messages 2021/08/05

[#104831] [Ruby master Bug#18066] Load did_you_mean eve/error_highlight even with --disable-gems — v.ondruch@...

Issue #18066 has been reported by vo.x (Vit Ondruch).

10 messages 2021/08/07

[#104851] [Ruby master Bug#18073] test/ruby/test_jit.rb: failures "error: invalid use of '__builtin_va_arg_pack ()'" on Ruby 2.7.4 on gcc 4.8.5 on RHEL7 — jaruga@...

Issue #18073 has been reported by jaruga (Jun Aruga).

14 messages 2021/08/09

[#104927] [Ruby master Bug#18077] Marshal.dump(closed_io) raises IOError instead of TypeError — "larskanis (Lars Kanis)" <noreply@...>

Issue #18077 has been reported by larskanis (Lars Kanis).

10 messages 2021/08/16

[#104960] [Ruby master Feature#18083] Capture error in ensure block. — "ioquatix (Samuel Williams)" <noreply@...>

Issue #18083 has been reported by ioquatix (Samuel Williams).

32 messages 2021/08/18

[#105021] [Ruby master Misc#18122] DevelopersMeeting20210916Japan — "mame (Yusuke Endoh)" <noreply@...>

Issue #18122 has been reported by mame (Yusuke Endoh).

12 messages 2021/08/20

[#105069] [Ruby master Bug#18133] LTO: TestGCCompact#test_ast_compacts segfaults on i686 — "vo.x (Vit Ondruch)" <noreply@...>

Issue #18133 has been reported by vo.x (Vit Ondruch).

25 messages 2021/08/25

[#105077] [Ruby master Feature#18136] take_while_after — "zverok (Victor Shepelev)" <noreply@...>

Issue #18136 has been reported by zverok (Victor Shepelev).

21 messages 2021/08/27

[ruby-core:105001] [Ruby master Feature#18083] Capture error in ensure block.

From: "ioquatix (Samuel Williams)" <noreply@...>
Date: 2021-08-19 08:04:43 UTC
List: ruby-core #105001
Issue #18083 has been updated by ioquatix (Samuel Williams).


We want to make it easy for people to write robust Ruby programs, even if there is failure. As discussed in <https://bugs.ruby-lang.org/issues/15567> there are some tricky edge cases when using `$!` because it's non-local state. As an example:

``` ruby
def do_work
  begin # $! may be set on entry to `begin`.
    # ... do work ...
  ensure
    if $!
      puts "work failed"
    else
      puts "work success"
    end
  end
end
 
begin
  raise "Boom"
ensure
  # $! is set.
  do_work
end
```

There are real examples of this kind of code: https://bugs.ruby-lang.org/issues/15567#note-26

There is another kind of error that can occur:

``` ruby
begin
  raise "Boom"
rescue => error
  # Ignore?
ensure
  pp error # <RuntimeError: Boom>
  pp $! # nil
end
```

As a general model, something like the following would be incredibly useful, and help guide people in the right direction:

``` ruby
begin
 ...
ensure => error
  pp "error occurred" if error
end
```

Currently you can almost achieve this:

``` ruby
begin
  ...
rescue Exception => error # RuboCop will complain.
  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 (e.g. care with `rescue ... => error` naming. Also, Rubocop will complain about it, which I think is generally correct since we shouldn't encourage users to `rescue Exception`.

Because `$!` can be buggy and encourage incorrect code, I also believe we should consider deprecating it. But in order to do so, we need to provide users with a functional alternative, e.g. `ensure => error`.

Another option is to clear `$!` when entering `begin` block (and maybe restore it on exit?), but this may break existing code.

#### More Examples

```
Gem: bundler has 1480241823 downloads.
/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb

  ensure
    return sleep_time unless $!

Gem: rubygems-update has 817517436 downloads.
/lib/rubygems/core_ext/kernel_require.rb

  ensure
    if RUBYGEMS_ACTIVATION_MONITOR.respond_to?(:mon_owned?)
      if monitor_owned != (ow = RUBYGEMS_ACTIVATION_MONITOR.mon_owned?)
        STDERR.puts [$$, Thread.current, $!, $!.backtrace].inspect if $!

Gem: launchy has 196850833 downloads.
/lib/launchy.rb

    ensure
      if $! and block_given? then
        yield $!

Gem: spring has 177806450 downloads.
/lib/spring/application.rb

          ensure
            if $!
              lib = File.expand_path("..", __FILE__)
              $!.backtrace.reject! { |line| line.start_with?(lib) }

Gem: net-http-persistent has 108254000 downloads.
/lib/net/http/persistent.rb

  ensure
    return sleep_time unless $!

Gem: open4 has 86007490 downloads.
/lib/open4.rb

            ensure
              killall rescue nil if $!

Gem: net-ssh-gateway has 74452292 downloads.
/lib/net/ssh/gateway.rb

    ensure
      close(local_port) if block || $!

Gem: vault has 48165849 downloads.
/lib/vault/persistent.rb

  ensure
    return sleep_time unless $!

Gem: webrick has 46884726 downloads.
/lib/webrick/httpauth/htgroup.rb

        ensure
          tmp.close
          if $!

Gem: stripe-ruby-mock has 11533268 downloads.
/lib/stripe_mock/api/server.rb

        ensure
          raise e if $! != e

Gem: logstash-input-udp has 8223308 downloads.
/lib/logstash/inputs/udp.rb

  ensure
    if @udp
      @udp.close_read rescue ignore_close_and_log($!)
      @udp.close_write rescue ignore_close_and_log($!)

Gem: shrine has 6332950 downloads.
/lib/shrine/uploaded_file.rb

      ensure
        tempfile.close! if ($! || block_given?) && tempfile

```

Discussion:
* nobu: `$!` is thread-local.
* ko1: Your proposal is to make shorthand for the following code?
  * mame: No

```ruby=
begin
 ...
ensure
  error = $!
  ...
end
```

* ko1: FYI

```ruby=
def foo
  p $! #=> #<RuntimeError: FOO>
  raise SyntaxError
rescue SyntaxError
end

begin
  raise 'FOO'
ensure
  foo; p $! #=> #<RuntimeError: FOO>
  exit
end
```

* mame: It is surprising to me that `$!` is not a method-local but a thread-local variable

```ruby=
at_exit do # |exception| ???
  if $! # exception
    puts "Exiting because of error"
  end
end
```

```ruby=
begin
  raise "Boom"
ensure
  begin
  ensure => error # should be nil - yes correct. This is the difference between ko1's workaround and samuel's proposal
    p $! #=> #<RuntimeError: Boom>
    error = $!
    puts "failed" if $!
  end
end
```

* knu:
```ruby=
begin
  Integer("foo")
rescue
  begin
    Integer("1")
  ensure => error
    # You can't tell `$!` came from this begin block without being rescued.
    p $!  #=> #<ArgumentError: invalid value for Integer(): "foo">
    p error #=> nil
  end
end
```

You can almost achieve the ideal situation with this:

``` ruby
begin
  ...
rescue Exception => error # RuboCop will complain.
  raise
ensure
  pp "error occurred" if error
end
```

----------------------------------------
Feature #18083: Capture error in ensure block.
https://bugs.ruby-lang.org/issues/18083#change-93400

* 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: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>

In This Thread