-
-
Notifications
You must be signed in to change notification settings - Fork 942
Description
In the Ruby MongoDB driver we have a module that requires an external C library. When this module is loaded it attempts to load the library, which could fail if the library is missing. We then autoload this module so that the user can reference it again later and, if the library is put in place, the module would work.
I converted our logic to the following reproduce shell script which creates two files, a.rb and t/b.rb, sets up B to be autoloaded from t/b.rb, but in t/b.rb there is only a LoadError raised:
mkdir -p t
cat > t/b.rb <<EOT
# This line is needed for 9.2, which would not attempt to autoload again otherwise.
# MRI and 9.3 do not need it.
autoload :B, 'b'
raise LoadError, 'custom message'
EOT
cat >a.rb <<EOT
$: << 't'
autoload :B, 'b'
begin
p B
rescue Exception => e
p e
end
p B
p 'done'
EOT
ruby a.rb
Having b.rb not in the current directory is important.
When this is run on MRI, it produces:
root@1d66935478aa:/# ruby -v
ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux-gnu]
root@1d66935478aa:/# mkdir -p t
root@1d66935478aa:/#
root@1d66935478aa:/# cat > t/b.rb <<EOT
> autoload :B, 'b'
> raise LoadError, 'custom message'
> EOT
root@1d66935478aa:/#
root@1d66935478aa:/# cat >a.rb <<EOT
> $: << 't'
> autoload :B, 'b'
> begin
> p B
> rescue Exception => e
> p e
> end
> p B
> p 'done'
> EOT
root@1d66935478aa:/#
root@1d66935478aa:/# ruby a.rb
#<LoadError: custom message>
Traceback (most recent call last):
3: from a.rb:8:in `<main>'
2: from /usr/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require'
1: from /usr/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require'
/t/b.rb:2:in `<top (required)>': custom message (LoadError)
LoadError with the custom message is raised twice.
Same result on 9.2:
root@1d66935478aa:/# ruby -v
jruby 9.2.20.1 (2.5.8) 2021-11-30 2a2962fbd1 OpenJDK 64-Bit Server VM 17.0.1+12-Ubuntu-120.04 on 17.0.1+12-Ubuntu-120.04 +jit [linux-x86_64]
root@1d66935478aa:/# mkdir -p t
root@1d66935478aa:/#
root@1d66935478aa:/# cat > t/b.rb <<EOT
> autoload :B, 'b'
> raise LoadError, 'custom message'
> EOT
root@1d66935478aa:/#
root@1d66935478aa:/# cat >a.rb <<EOT
> $: << 't'
> autoload :B, 'b'
> begin
> p B
> rescue Exception => e
> p e
> end
> p B
> p 'done'
> EOT
root@1d66935478aa:/#
root@1d66935478aa:/# ruby a.rb
#<LoadError: custom message>
LoadError: custom message
<main> at /t/b.rb:2
<main> at a.rb:8
On 9.3 the second exception is converted to NameError and the custom message is discarded:
root@1d66935478aa:/# ruby -v
jruby 9.3.3.0 (2.6.8) 2022-01-19 b26de1f5c5 OpenJDK 64-Bit Server VM 17.0.1+12-Ubuntu-120.04 on 17.0.1+12-Ubuntu-120.04 +jit [linux-x86_64]
root@1d66935478aa:/# mkdir -p t
root@1d66935478aa:/#
root@1d66935478aa:/# cat > t/b.rb <<EOT
> autoload :B, 'b'
> raise LoadError, 'custom message'
> EOT
root@1d66935478aa:/#
root@1d66935478aa:/# cat >a.rb <<EOT
> $: << 't'
> autoload :B, 'b'
> begin
> p B
> rescue Exception => e
> p e
> end
> p B
> p 'done'
> EOT
root@1d66935478aa:/#
root@1d66935478aa:/# ruby a.rb
#<LoadError: custom message>
NameError: uninitialized constant B
const_missing at org/jruby/RubyModule.java:3950
<main> at a.rb:8
If b.rb is in the current directory, the second exception is retained as LoadError with the custom message:
cat > b.rb <<EOT
autoload :B, 'b'
raise LoadError, 'custom message'
EOT
cat >a.rb <<EOT
$: << '.'
autoload :B, 'b'
begin
p B
rescue Exception => e
p e
end
p B
p 'done'
EOT
ruby a.rb
root@1d66935478aa:/# ruby -v
jruby 9.3.3.0 (2.6.8) 2022-01-19 b26de1f5c5 OpenJDK 64-Bit Server VM 17.0.1+12-Ubuntu-120.04 on 17.0.1+12-Ubuntu-120.04 +jit [linux-x86_64]
root@1d66935478aa:/# cat > b.rb <<EOT
> autoload :B, 'b'
> raise LoadError, 'custom message'
> EOT
root@1d66935478aa:/#
root@1d66935478aa:/# cat >a.rb <<EOT
> $: << '.'
> autoload :B, 'b'
> begin
> p B
> rescue Exception => e
> p e
> end
> p B
> p 'done'
> EOT
root@1d66935478aa:/#
root@1d66935478aa:/# ruby a.rb
#<LoadError: custom message>
LoadError: custom message
<main> at /b.rb:2
require at org/jruby/RubyKernel.java:1017
require at /root/.rbenv/versions/jruby-9.3.3.0/lib/ruby/stdlib/rubygems/core_ext/kernel_require.rb:85
<main> at a.rb:8