Skip to content

Bundler.bin_path writes to the filesystem when it should be an attribute reader #9197

@p-datadog

Description

@p-datadog

Describe the problem as clearly as you can

Bundler.bin_path looks like a simple attribute reader, is documented as such, but performs filesystem writes:

def bin_path
@bin_path ||= begin
path = Bundler.settings[:bin] || "bin"
path = Pathname.new(path).expand_path(root).expand_path
mkdir_p(path)
path
end
end

    # Returns absolute location of where binstubs are installed to.
    def bin_path
      @bin_path ||= begin
        path = Bundler.settings[:bin] || "bin"
        path = Pathname.new(path).expand_path(root).expand_path
        mkdir_p(path)
        path
      end
    end

The writes fail on read-only filesystems, and writing to filesystem is not expected behavior when one is trying to find out "where binstubs are installed to".

More information: DataDog/dd-trace-rb#5137

Did you try upgrading rubygems & bundler?

Problematic code is in master

Post steps to reproduce the problem

big# modprobe zram
big# zramctl -s 1g -f
/dev/zram0
big# mkfs.ext2 /dev/zram0 
mke2fs 1.46.5 (30-Dec-2021)
Discarding device blocks: done                            
Creating filesystem with 262144 4k blocks and 65536 inodes
Filesystem UUID: 35fbb153-fd4e-4637-b912-5df653bbf4bb
Superblock backups stored on blocks: 
        32768, 98304, 163840, 229376

Allocating group tables: done                            
Writing inode tables: done                            
Writing superblocks and filesystem accounting information: done

big# mount -o ro /dev/zram0 /mnt/tmp 
big# su - sandbox
big% bundle config bin /mnt/tmp/bin
big% echo 'source "https://rubygems.org"' >Gemfile
big% irb -rbundler                                
irb(main):001:0> Bundler.bin_path
/usr/share/rubygems-integration/all/gems/bundler-2.3.5/lib/bundler/shared_helpers.rb:117:in `rescue in filesystem_access': There was an error accessing `/mnt/tmp/bin`. (Bundler::GenericSystemCallError)
The underlying system error is Errno::EROFS: Read-only file system @ dir_s_mkdir - /mnt/tmp/bin
        from /usr/share/rubygems-integration/all/gems/bundler-2.3.5/lib/bundler/shared_helpers.rb:102:in `filesystem_access'
        from /usr/share/rubygems-integration/all/gems/bundler-2.3.5/lib/bundler.rb:109:in `bin_path'
        from (irb):1:in `<main>'
        from /usr/lib/ruby/gems/3.0.0/gems/irb-1.3.5/exe/irb:11:in `<top (required)>'
        from /usr/bin/irb:23:in `load'
        from /usr/bin/irb:23:in `<main>'
/usr/share/rubygems-integration/all/gems/bundler-2.3.5/lib/bundler/vendor/fileutils/lib/fileutils.rb:250:in `mkdir': Read-only file system @ dir_s_mkdir - /mnt/tmp/bin (Errno::EROFS)
        from /usr/share/rubygems-integration/all/gems/bundler-2.3.5/lib/bundler/vendor/fileutils/lib/fileutils.rb:250:in `fu_mkdir'
        from /usr/share/rubygems-integration/all/gems/bundler-2.3.5/lib/bundler/vendor/fileutils/lib/fileutils.rb:228:in `block (2 levels) in mkdir_p'
        from /usr/share/rubygems-integration/all/gems/bundler-2.3.5/lib/bundler/vendor/fileutils/lib/fileutils.rb:226:in `reverse_each'
        from /usr/share/rubygems-integration/all/gems/bundler-2.3.5/lib/bundler/vendor/fileutils/lib/fileutils.rb:226:in `block in mkdir_p'
        from /usr/share/rubygems-integration/all/gems/bundler-2.3.5/lib/bundler/vendor/fileutils/lib/fileutils.rb:211:in `each'
        from /usr/share/rubygems-integration/all/gems/bundler-2.3.5/lib/bundler/vendor/fileutils/lib/fileutils.rb:211:in `mkdir_p'
        from /usr/share/rubygems-integration/all/gems/bundler-2.3.5/lib/bundler.rb:109:in `block in bin_path'
        from /usr/share/rubygems-integration/all/gems/bundler-2.3.5/lib/bundler/shared_helpers.rb:103:in `filesystem_access'
        from /usr/share/rubygems-integration/all/gems/bundler-2.3.5/lib/bundler.rb:109:in `bin_path'
        from (irb):1:in `<main>'
        from /usr/lib/ruby/gems/3.0.0/gems/irb-1.3.5/exe/irb:11:in `<top (required)>'
        from /usr/bin/irb:23:in `load'
        from /usr/bin/irb:23:in `<main>'

Which command did you run?

What were you expecting to happen?

Bundler.bin_path should return the bin path and not perform any filesystem writes.

What happened instead?

Bundler writes (tries to write) to the filesystem.

Replace this with the actual result you got. Paste the output of your command here.

If not included with the output of your command, run bundle env and paste the output below

Not relevant

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions