[#101981] [Ruby master Bug#17519] set_visibility fails when a prepended module and a refinement both exist — dbfeldman@...

Issue #17519 has been reported by fledman (David Feldman).

12 messages 2021/01/08

[#102003] [Ruby master Bug#17527] rb_io_wait_readable/writable with scheduler don't check errno — julien@...

Issue #17527 has been reported by ysbaddaden (Julien Portalier).

13 messages 2021/01/11

[#102065] [Ruby master Bug#17536] Segfault in `CFUNC :define_method` — v.ondruch@...

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

13 messages 2021/01/13

[#102083] [Ruby master Bug#17540] A segfault due to Clang/LLVM optimization on 32-bit ARM Linux — xtkoba+ruby@...

Issue #17540 has been reported by xtkoba (Tee KOBAYASHI).

12 messages 2021/01/14

[#102102] [Ruby master Bug#17543] Ractor isolation broken by `self` in shareable proc — marcandre-ruby-core@...

Issue #17543 has been reported by marcandre (Marc-Andre Lafortune).

14 messages 2021/01/15

[#102118] [Ruby master Feature#17548] Need simple way to include symlink directories in Dir.glob — keithrbennett@...

Issue #17548 has been reported by keithrbennett (Keith Bennett).

8 messages 2021/01/17

[#102158] [Ruby master Bug#17560] Does `Module#ruby2_keywords` return `nil` or `self`? — nobu@...

Issue #17560 has been reported by nobu (Nobuyoshi Nakada).

9 messages 2021/01/19

[#102163] [Ruby master Bug#17561] The timeout option for Addrinfo.getaddrinfo is not reliable on Ruby 2.7.2 — sean@...

Issue #17561 has been reported by smcgivern (Sean McGivern).

8 messages 2021/01/19

[#102249] [Ruby master Bug#17583] Segfault on large stack(RUBY_THREAD_VM_STACK_SIZE) — yoshiokatsuneo@...

Issue #17583 has been reported by yoshiokatsuneo (Tsuneo Yoshioka).

12 messages 2021/01/26

[#102256] [Ruby master Bug#17585] DWAR5 support? — v.ondruch@...

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

19 messages 2021/01/26

[#102301] [Ruby master Bug#17591] Test frameworks and REPLs do not show deprecation warnings by default — eregontp@...

Issue #17591 has been reported by Eregon (Benoit Daloze).

14 messages 2021/01/29

[#102305] [Ruby master Feature#17592] Ractor should allowing reading shareable class instance variables — marcandre-ruby-core@...

Issue #17592 has been reported by marcandre (Marc-Andre Lafortune).

25 messages 2021/01/29

[ruby-core:102310] [Ruby master Feature#17593] load_iseq_eval should override the ISeq path

From: jean.boussier@...
Date: 2021-01-29 18:05:43 UTC
List: ruby-core #102310
Issue #17593 has been reported by byroot (Jean Boussier).

----------------------------------------
Feature #17593: load_iseq_eval should override the ISeq path
https://bugs.ruby-lang.org/issues/17593

* Author: byroot (Jean Boussier)
* Status: Open
* Priority: Normal
----------------------------------------
Full context in https://github.com/Shopify/bootsnap/pull/343

Consider the following script

```ruby
system('mkdir', '-p', '/tmp/build', '/tmp/app')
File.write('/tmp/app/a.rb', 'p ["app/a", __FILE__, __dir__]')
File.write('/tmp/app/b.rb', 'p ["app/b", __FILE__, __dir__]')
File.write('/tmp/build/a.rb', 'p ["build/a", __FILE__, __dir__]; require_relative "b"')

$iseq = RubyVM::InstructionSequence.compile_file('/tmp/build/a.rb')

class RubyVM::InstructionSequence
  def self.load_iseq(feature)
    if feature == "/tmp/app/a.rb"
      $iseq
    end
  end
end

require '/tmp/app/a.rb'
```

Current behavior:

```ruby
["build/a", "/tmp/build/a.rb", "/private/tmp/build"]
/tmp/build/a.rb:1:in `require_relative': cannot load such file -- /private/tmp/build/b (LoadError)
	from /tmp/build/a.rb:1:in `<main>'
	from <internal:/opt/rubies/3.0.0-pshopify2/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
	from <internal:/opt/rubies/3.0.0-pshopify2/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb>:85:in `require'
	from /tmp/iseq_debug.rb:16:in `<main>'
```

Expected behavior

```ruby
["build/a", "/private/tmp/app/a.rb", "/private/tmp/app"]
["app/b", "/private/tmp/app/b.rb", "/private/tmp/app"]
```

### What's going on?

`RubyVM::InstructionSequence` instances have a `pathobj` property that is recorded when the source is parsed, and when the ISeq is later evaled, the VM use that `path` as if you were loading a `.rb` file located at that path.

So if that source use constructs such as `require_relative`, `__FILE__`, `__dir__`, etc, they will all happen relative to where the source was located upon compilation, not relative to the source was upon evaluation.

### Why is it a problem?

Some deployment strategies first build the application in one location, and then later move it elsewhere. 

That's for instance the case on the Heroku platform. e.g. the deploy looks like

```bash
git clone <repo> /tmp/build_xxxx
cd /tmp/build_xxxx
rake assets:precompile ...
mv /tmp/build_xxxx /app
```

Because of this, all the ISeq cached by bootsnap when the code was in `/tmp/build_xxx` have to be invalidated as soon as the source is moved to `/app`, rendering ISeq caching ineffective, and even detrimental as it causes extra writes to disk without bringing any benefits.

### Solution

I believe there are two changes that would be needed.

First I think that `load_iseq_eval` should set the `fname` as the top stack location. Either by copying the ISeq instance and change its `pathobj`, or by having a way to pass an optional path to `vm_set_top_stack` that would take precedence.

I experimented with [a quick hack that changes the ISeq `pathobj` in place](https://github.com/Shopify/ruby/commit/192f5b477f924243e3f6621383e7a6ad02fbd63d), and it does solve most of the problem.

However even with that quick hack another problem remain, the `__FILE__` still evaluate to the original source location. However `__dir__` works as expected, because it is a method that returns the top_stack location. I think `__FILE__` could be changed to be a method as well.



-- 
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

Prev Next